From b5cec447bd8f07b9af5a79dc465f3f003abad94c Mon Sep 17 00:00:00 2001 From: hunili Date: Thu, 4 Sep 2025 10:14:39 +0800 Subject: [PATCH] =?UTF-8?q?[Bug]:=20=E4=BA=91=E7=9B=98=5F001=20https://git?= =?UTF-8?q?ee.com/openharmony/filemanagement=5Fuser=5Ffile=5Fservice/issue?= =?UTF-8?q?s/ICWA8P?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hunili --- .../include/cloud_disk_comm.h | 60 ++++ .../src/cloud_disk_comm.cpp | 126 ++++++++ interfaces/inner_api/file_access/BUILD.gn | 2 + services/BUILD.gn | 10 +- services/IFileAccessServiceBase.idl | 9 + .../src/cloud_disk_service.cpp | 134 ++++++++ .../include/file_access_service.h | 16 +- .../src/file_access_service.cpp | 9 +- .../include/notify_work_service.h | 39 +++ .../notify_event/src/notify_work_service.cpp | 66 ++++ test/unittest/BUILD.gn | 160 +++++++++- test/unittest/cloud_disk_comm_test.cpp | 298 ++++++++++++++++++ test/unittest/cloud_disk_service_test.cpp | 232 ++++++++++++++ .../js_file_access_ext_ability_test.cpp | 35 ++ test/unittest/mock/file_access_service_mock.h | 7 + test/unittest/mock/message_parcel_mock.cpp | 10 +- test/unittest/mock/message_parcel_mock.h | 4 +- test/unittest/notify_work_service_test.cpp | 142 +++++++++ utils/file_access_framework_errno.h | 23 +- 19 files changed, 1368 insertions(+), 14 deletions(-) create mode 100644 interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h create mode 100644 interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp create mode 100644 services/native/cloud_disk_service/src/cloud_disk_service.cpp create mode 100644 services/native/notify_event/include/notify_work_service.h create mode 100644 services/native/notify_event/src/notify_work_service.cpp create mode 100644 test/unittest/cloud_disk_comm_test.cpp create mode 100644 test/unittest/cloud_disk_service_test.cpp create mode 100644 test/unittest/notify_work_service_test.cpp diff --git a/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.h new file mode 100644 index 00000000..5753b57a --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/include/cloud_disk_comm.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 CLOUD_DISK_COMMON_H +#define CLOUD_DISK_COMMON_H + +#include "parcel.h" + +#ifndef CLOUD_DISK_EXPORT +#define CLOUD_DISK_EXPORT __attribute__((visibility("default"))) +#endif + +namespace OHOS { +namespace FileManagement { + enum class State { + INACTIVE, + ACTIVE, + MAX_VALUE + }; + + struct SyncFolder : public OHOS::Parcelable { + std::string path_; + State state_ { State::INACTIVE }; + uint32_t displayNameResId_ { 0 }; // 0: default resId value + std::string displayName_; + + SyncFolder() = default; + SyncFolder(const std::string &path, State state, uint32_t resId, const std::string &displayName) + :path_(path), state_(state), displayNameResId_(resId), displayName_(displayName) {} + bool Marshalling(Parcel &parcel) const override; + bool ReadFromParcel(Parcel &parcel); + static SyncFolder *Unmarshalling(Parcel &parcel); + }; + + struct SyncFolderExt : SyncFolder { + std::string bundleName_; + + SyncFolderExt() = default; + SyncFolderExt(const std::string &path, + State state, uint32_t resId, const std::string &displayName, const std::string &bundleName) + :SyncFolder(path, state, resId, displayName), bundleName_(bundleName) {} + bool Marshalling(Parcel &parcel) const override; + bool ReadFromParcel(Parcel &parcel); + static SyncFolderExt *Unmarshalling(Parcel &parcel); + }; +} // namespace FileManagement +} // namespace OHOS +#endif // CLOUD_DISK_COMMON_H \ No newline at end of file diff --git a/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp new file mode 100644 index 00000000..dff06da4 --- /dev/null +++ b/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_disk_comm.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace FileManagement { +bool SyncFolder::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(path_)) { + HILOG_ERROR("write path failed"); + return false; + } + if (!parcel.WriteInt32(static_cast(state_))) { + HILOG_ERROR("write state failed"); + return false; + } + if (!parcel.WriteUint32(displayNameResId_)) { + HILOG_ERROR("write resId failed"); + return false; + } + if (!parcel.WriteString(displayName_)) { + HILOG_ERROR("write displayName failed"); + return false; + } + return true; +} + +bool SyncFolder::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(path_)) { + HILOG_ERROR("read path failed"); + return false; + } + int32_t state = 0; + if (!parcel.ReadInt32(state)) { + HILOG_ERROR("read state failed"); + return false; + } + if (state < static_cast(State::INACTIVE) || state >= static_cast(State::MAX_VALUE)) { + HILOG_ERROR("state check failed, read state is: %{public}d", state); + return false; + } + state_ = static_cast(state); + if (!parcel.ReadUint32(displayNameResId_)) { + HILOG_ERROR("read resId failed"); + return false; + } + if (!parcel.ReadString(displayName_)) { + HILOG_ERROR("read displayName failed"); + return false; + } + return true; +} + +SyncFolder *SyncFolder::Unmarshalling(Parcel &parcel) +{ + SyncFolder *info = new (std::nothrow) SyncFolder(); + if (info == nullptr) { + HILOG_ERROR("new syncFolder failed"); + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + HILOG_ERROR("syncFolder ReadFromParcel failed"); + delete info; + info = nullptr; + } + return info; +} + +bool SyncFolderExt::Marshalling(Parcel &parcel) const +{ + if (!SyncFolder::Marshalling(parcel)) { + HILOG_ERROR("syncFolder marshalling failed"); + return false; + } + if (!parcel.WriteString(bundleName_)) { + HILOG_ERROR("write bundleName failed"); + return false; + } + return true; +} + +bool SyncFolderExt::ReadFromParcel(Parcel &parcel) +{ + if (!SyncFolder::ReadFromParcel(parcel)) { + HILOG_ERROR("syncFolder ReadFromParcel failed"); + return false; + } + if (!parcel.ReadString(bundleName_)) { + HILOG_ERROR("read bundleName failed"); + return false; + } + return true; +} + +SyncFolderExt *SyncFolderExt::Unmarshalling(Parcel &parcel) +{ + SyncFolderExt *info = new (std::nothrow) SyncFolderExt(); + if (info == nullptr) { + HILOG_ERROR("new syncFolderExt failed"); + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + HILOG_ERROR("syncFolderExt ReadFromParcel failed"); + delete info; + info = nullptr; + } + return info; +} +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/file_access/BUILD.gn b/interfaces/inner_api/file_access/BUILD.gn index fb401d91..0401b960 100644 --- a/interfaces/inner_api/file_access/BUILD.gn +++ b/interfaces/inner_api/file_access/BUILD.gn @@ -29,6 +29,7 @@ config("IFile_Access_Ext_Base_config") { "${user_file_service_path}/utils", "${user_file_service_path}/services/native/file_access_service/include", "${user_file_service_path}/interfaces/kits/js/src/common", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${target_gen_dir}", ] } @@ -128,6 +129,7 @@ ohos_shared_library("file_access_extension_ability_kit") { ] sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/services/native/file_access_service/src/file_access_service_client.cpp", "src/app_file_access_ext_connection.cpp", "src/file_access_ext_ability.cpp", diff --git a/services/BUILD.gn b/services/BUILD.gn index d0441abd..b269f07e 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -174,15 +174,20 @@ ohos_shared_library("file_access_service") { } include_dirs = [ - "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/services/native/notify_event/include" ] shlib_type = "sa" sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", + "native/cloud_disk_service/src/cloud_disk_service.cpp", "native/file_access_service/src/file_access_ext_connection.cpp", "native/file_access_service/src/file_access_service.cpp", "native/file_access_service/src/file_access_service_client.cpp", + "native/notify_event/src/notify_work_service.cpp" ] configs = [ ":ability_config" ] version_script = "libfile_access_service.map" @@ -203,12 +208,13 @@ ohos_shared_library("file_access_service") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "bundle_framework:appexecfwk_core", + "common_event_service:cesfwk_innerkits", "c_utils:utils", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_core", "safwk:system_ability_fwk", - "samgr:samgr_proxy", + "samgr:samgr_proxy" ] subsystem_name = "filemanagement" diff --git a/services/IFileAccessServiceBase.idl b/services/IFileAccessServiceBase.idl index 704913b0..efb2813c 100644 --- a/services/IFileAccessServiceBase.idl +++ b/services/IFileAccessServiceBase.idl @@ -18,6 +18,8 @@ import IFileAccessObserver; sequenceable Uri..OHOS.Uri; sequenceable FileAccessExtensionInfo..OHOS.FileAccessFwk.ConnectExtensionInfo; sequenceable Want..OHOS.AAFwk.Want; +sequenceable CloudDiskComm..OHOS.FileManagement.SyncFolder; +sequenceable CloudDiskComm..OHOS.FileManagement.SyncFolderExt; interface OHOS.FileAccessFwk.IFileAccessExtBase; interface OHOS.AAFwk.IAbilityConnection; interface OHOS.FileAccessFwk.IFileAccessServiceBase { @@ -29,4 +31,11 @@ interface OHOS.FileAccessFwk.IFileAccessServiceBase { void ConnectFileExtAbility([in] Want want, [in] IAbilityConnection connection); void DisConnectFileExtAbility([in] IAbilityConnection connection); void UnregisterNotifyNoObserver([in] Uri uri, [in] ConnectExtensionInfo info); + void Register([in] SyncFolder syncFolder); + void Unregister([in] String path); + void Active([in] String path); + void Deactive([in] String path); + void GetSyncFolders([out] SyncFolder[] syncFolders); + void GetAllSyncFolders([out] SyncFolderExt[] syncFolderExts); + void UpdateDisplayName([in] String path, [in] String displayName); } \ No newline at end of file diff --git a/services/native/cloud_disk_service/src/cloud_disk_service.cpp b/services/native/cloud_disk_service/src/cloud_disk_service.cpp new file mode 100644 index 00000000..b92262ba --- /dev/null +++ b/services/native/cloud_disk_service/src/cloud_disk_service.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 "file_access_service.h" +#include "notify_work_service.h" + +using namespace std; +namespace OHOS { +namespace FileAccessFwk { + +void FileAccessService::IncreaseCnt(const std::string &funcName) +{ + std::lock_guard lock(calledMutex_); + ++calledCount_; + HILOG_INFO("Func name: %{public}s, count: %{public}d", funcName.c_str(), calledCount_.load()); +} + +void FileAccessService::DecreaseCnt(const std::string &funcName) +{ + std::lock_guard lock(calledMutex_); + if (calledCount_.load() > 0) { + --calledCount_; + } else { + HILOG_ERROR("Invalid calledCount."); + } + HILOG_INFO("Func name: %{public}s, count: %{public}d", funcName.c_str(), calledCount_.load()); +} + +bool FileAccessService::IsCalledCountValid() +{ + std::lock_guard lock(calledMutex_); + return calledCount_.load() > 0; +} + +int32_t FileAccessService::Register(const SyncFolder &syncFolder) +{ + HILOG_INFO("FileAccessService::Register begin"); + IncreaseCnt(__func__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = syncFolder.path_; + if (!NotifyWorkService::GetInstance().NotifySyncFolderEvent(syncFolderExt, + NotifyWorkService::EventType::REGISTER)) { + HILOG_ERROR("FileAccessService::Register NotifySyncFolderEvent failed"); + } + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::Unregister(const std::string &path) +{ + HILOG_INFO("FileAccessService::Unregister begin"); + IncreaseCnt(__func__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + if (!NotifyWorkService::GetInstance().NotifySyncFolderEvent(syncFolderExt, + NotifyWorkService::EventType::UNREGISTER)) { + HILOG_ERROR("FileAccessService::Unregister NotifySyncFolderEvent failed"); + } + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::Active(const std::string &path) +{ + HILOG_INFO("FileAccessService::Active begin"); + IncreaseCnt(__func__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + if (!NotifyWorkService::GetInstance().NotifySyncFolderEvent(syncFolderExt, + NotifyWorkService::EventType::ACTIVE)) { + HILOG_ERROR("FileAccessService::Active NotifySyncFolderEvent failed"); + } + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::Deactive(const std::string &path) +{ + HILOG_INFO("FileAccessService::Deactive begin"); + IncreaseCnt(__func__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + if (!NotifyWorkService::GetInstance().NotifySyncFolderEvent(syncFolderExt, + NotifyWorkService::EventType::INACTIVE)) { + HILOG_ERROR("FileAccessService::Deactive NotifySyncFolderEvent failed"); + } + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::GetSyncFolders(std::vector &syncFolders) +{ + HILOG_INFO("FileAccessService::GetSyncFolders begin"); + IncreaseCnt(__func__); + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::GetAllSyncFolders(std::vector &syncFolderExts) +{ + HILOG_INFO("FileAccessService::GetAllSyncFolders begin"); + IncreaseCnt(__func__); + DecreaseCnt(__func__); + return ERR_OK; +} + +int32_t FileAccessService::UpdateDisplayName(const std::string &path, const std::string &displayName) +{ + HILOG_INFO("FileAccessService::UpdateDisplayName begin"); + IncreaseCnt(__func__); + SyncFolderExt syncFolderExt; + syncFolderExt.path_ = path; + syncFolderExt.displayName_ = displayName; + if (!NotifyWorkService::GetInstance().NotifySyncFolderEvent(syncFolderExt, + NotifyWorkService::EventType::UPDATE)) { + HILOG_ERROR("FileAccessService::UpdateDisplayName NotifySyncFolderEvent failed"); + } + DecreaseCnt(__func__); + return ERR_OK; +} +} // namespace FileAccessFwk +} // namespace OHOS diff --git a/services/native/file_access_service/include/file_access_service.h b/services/native/file_access_service/include/file_access_service.h index b24e0c47..143cc854 100644 --- a/services/native/file_access_service/include/file_access_service.h +++ b/services/native/file_access_service/include/file_access_service.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2025 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 @@ -245,6 +245,13 @@ protected: int32_t ConnectFileExtAbility(const AAFwk::Want &want, const sptr& connection) override; int32_t DisConnectFileExtAbility(const sptr& connection) override; + int32_t Register(const SyncFolder &syncFolder) override; + int32_t Unregister(const std::string &path) override; + int32_t Active(const std::string &path) override; + int32_t Deactive(const std::string &path) override; + int32_t GetSyncFolders(std::vector &syncFolder) override; + int32_t GetAllSyncFolders(std::vector &syncFolderExt) override; + int32_t UpdateDisplayName(const std::string &path, const std::string &displayName) override; private: class ExtensionDeathRecipient : public IRemoteObject::DeathRecipient { @@ -285,6 +292,9 @@ private: void AddExtProxyInfo(std::string bundleName, sptr extProxy); // 管理对象 方法 void AddAppProxy(const sptr& key, sptr& value); + void IncreaseCnt(const std::string &funcName); + void DecreaseCnt(const std::string &funcName); + bool IsCalledCountValid(); std::shared_ptr unLoadTimer_ = nullptr; std::shared_ptr onDemandTimer_ = nullptr; static sptr instance_; @@ -298,7 +308,7 @@ private: HolderManager> obsManager_; std::mutex mapMutex_; std::unordered_map> cMap_; - + class AppDeathRecipient : public IRemoteObject::DeathRecipient { public: AppDeathRecipient() {} @@ -310,6 +320,8 @@ private: std::unordered_map> appProxyMap_; std::unordered_map> appConnection_; sptr appDeathRecipient_; + std::atomic calledCount_{0}; + std::mutex calledMutex_; }; } // namespace FileAccessFwk } // namespace OHOS diff --git a/services/native/file_access_service/src/file_access_service.cpp b/services/native/file_access_service/src/file_access_service.cpp index e87c99cf..49b311e2 100644 --- a/services/native/file_access_service/src/file_access_service.cpp +++ b/services/native/file_access_service/src/file_access_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2025 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 @@ -683,9 +683,9 @@ int32_t FileAccessService::OnChange(const Uri &uri, NotifyType notifyType) bool FileAccessService::IsUnused() { - HILOG_INFO("IsUnused: obsManager_: %{public}d, appProxyMap_: %{public}d", - obsManager_.isEmpty(), appProxyMap_.empty()); - return obsManager_.isEmpty() && appProxyMap_.empty(); + HILOG_INFO("IsUnused: obsManager_: %{public}d, appProxyMap_: %{public}d, calledCount_: %{public}d", + obsManager_.isEmpty(), appProxyMap_.empty(), calledCount_.load()); + return obsManager_.isEmpty() && appProxyMap_.empty() && !IsCalledCountValid(); } void FileAccessService::InitTimer() @@ -906,6 +906,5 @@ void FileAccessService::AppDeathRecipient::OnRemoteDied(const wptrRemoveAppProxy(remoteBroker); } - } // namespace FileAccessFwk } // namespace OHOS diff --git a/services/native/notify_event/include/notify_work_service.h b/services/native/notify_event/include/notify_work_service.h new file mode 100644 index 00000000..a36d5ad5 --- /dev/null +++ b/services/native/notify_event/include/notify_work_service.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_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H +#define OHOS_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H + +#include "cloud_disk_comm.h" +namespace OHOS::FileAccessFwk { +class NotifyWorkService { +public: + enum class EventType { + REGISTER, + UNREGISTER, + ACTIVE, + INACTIVE, + UPDATE, + MAX_EVENT_TYPE + }; + static NotifyWorkService &GetInstance(); + bool NotifySyncFolderEvent(const FileManagement::SyncFolderExt &syncFolderExt, EventType eventType); +private: + NotifyWorkService() = default; + ~NotifyWorkService() = default; +}; +} // namespace OHOS::FileAccessFwk + +#endif // OHOS_FILEMGMT_CLOUD_DISK_NOTIFY_WORK_SERVICE_H \ No newline at end of file diff --git a/services/native/notify_event/src/notify_work_service.cpp b/services/native/notify_event/src/notify_work_service.cpp new file mode 100644 index 00000000..bd8131c9 --- /dev/null +++ b/services/native/notify_event/src/notify_work_service.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 "notify_work_service.h" + +#include "common_event_data.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "hilog_wrapper.h" +#include "want.h" +#include "want_params.h" + +namespace OHOS::FileAccessFwk { +constexpr const char *NOTIFY_EVENT_TYPES[] = { + "REGISTER", + "UNREGISTER", + "ACTIVE", + "INACTIVE", + "UPDATE" +}; + +NotifyWorkService &NotifyWorkService::GetInstance() +{ + static NotifyWorkService instance; + return instance; +} + +bool NotifyWorkService::NotifySyncFolderEvent(const FileManagement::SyncFolderExt &rootInfoExt, + NotifyWorkService::EventType eventType) +{ + AAFwk::Want want; + HILOG_INFO("Start publish event, bundleName is: %{public}s", rootInfoExt.bundleName_.c_str()); + want.SetBundle(rootInfoExt.bundleName_); + want.SetParam("bundleName", rootInfoExt.bundleName_); + if (eventType < EventType::REGISTER || eventType >= EventType::MAX_EVENT_TYPE) { + HILOG_ERROR("EventType is invalid: %{public}d", static_cast(eventType)); + return false; + } + want.SetParam("eventType", NOTIFY_EVENT_TYPES[static_cast(eventType)]); + want.SetParam("path", rootInfoExt.path_); + want.SetParam("state", static_cast(rootInfoExt.state_)); + if (rootInfoExt.displayNameResId_ != 0) { + want.SetParam("displayNameResId", std::to_string(rootInfoExt.displayNameResId_)); + } + if (!rootInfoExt.displayName_.empty()) { + want.SetParam("displayName", rootInfoExt.displayName_); + } + want.SetAction("usual.event.CLOUD_DISK_STATE_CHANGED"); + EventFwk::CommonEventData commonData {want}; + HILOG_INFO("End publish event, bundleName is: %{public}s, eventType: %{public}s", + rootInfoExt.bundleName_.c_str(), NOTIFY_EVENT_TYPES[static_cast(eventType)]); + return EventFwk::CommonEventManager::PublishCommonEvent(commonData); +} +} \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 1e41b55e..64ddccaf 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -27,7 +27,7 @@ ohos_unittest("external_file_access_basic_test") { sources = [ "external_file_access_test.cpp", "external_file_access_test_basic.cpp", - "external_file_access_test_info.cpp", + "external_file_access_test_info.cpp" ] include_dirs = [ @@ -193,6 +193,7 @@ ohos_unittest("abnormal_file_access_test") { module_out_path = "user_file_service/user_file_service" sources = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp", "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", "abnormal_file_access_test.cpp", ] @@ -295,6 +296,7 @@ ohos_unittest("js_file_access_ext_ability_test") { module_out_path = "user_file_service/user_file_service" include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", "${user_file_service_path}/interfaces/inner_api/file_access/include", "${user_file_service_path}/interfaces/inner_api/file_access/src", "${user_file_service_path}/interfaces/kits/js/src/common", @@ -371,16 +373,172 @@ ohos_unittest("urie_test") { defines = [ "private=public" ] } +ohos_unittest("cloud_disk_service_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${user_file_service_path}/cfi_blocklist.txt" + } + module_out_path = "user_file_service/user_file_service" + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/file_access_service/include", + "${user_file_service_path}/services/native/notify_event/include", + "${user_file_service_path}/utils", + "mock", + ] + + sources = [ + "cloud_disk_service_test.cpp", + ] + + deps = [ + "${user_file_service_path}/services:file_access_service", + "${user_file_service_path}/services:file_access_service_base_source", + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_ext_base_include", + "${user_file_service_path}/interfaces/inner_api/file_access:file_access_extension_ability_kit", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + "safwk:system_ability_fwk" + ] + + defines = [ + "private=public", + "protected=public" + ] + + use_exceptions = true +} + +ohos_unittest("notify_work_service_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${user_file_service_path}/cfi_blocklist.txt" + } + module_out_path = "user_file_service/user_file_service" + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/notify_event/include", + "${user_file_service_path}/utils", + "mock", + ] + + sources = [ + "notify_work_service_test.cpp", + ] + + deps = [ + "${user_file_service_path}/services:file_access_service", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "file_api:filemgmt_libn", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "os_account:os_account_innerkits", + "common_event_service:cesfwk_innerkits", + ] + + defines = [ "private=public" ] + + use_exceptions = true +} + +ohos_unittest("cloud_disk_comm_test") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + cfi = true + cfi_cross_dso = true + debug = false + } + module_out_path = "user_file_service/user_file_service" + + sources = [ + "cloud_disk_comm_test.cpp", + "mock/message_parcel_mock.cpp", + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/src/cloud_disk_comm.cpp" + ] + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/cloud_disk_kit_inner/include", + "${user_file_service_path}/test/unittest/mock", + "${user_file_service_path}/utils" + ] + + configs = [ "//build/config/compiler:exceptions" ] + + external_deps = [ + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:rpc" + ] + + defines = [ "private=public" ] + testonly = true +} + group("user_file_service_unit_test") { testonly = true deps = [ ":abnormal_file_access_test", + ":cloud_disk_service_test", ":external_file_access_basic_test", ":external_file_access_management_test", ":external_file_access_notify_test", ":file_access_ext_stub_impl_test", ":js_file_access_ext_ability_test", + ":notify_work_service_test", ":urie_test", ] } \ No newline at end of file diff --git a/test/unittest/cloud_disk_comm_test.cpp b/test/unittest/cloud_disk_comm_test.cpp new file mode 100644 index 00000000..24ec7b60 --- /dev/null +++ b/test/unittest/cloud_disk_comm_test.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_disk_comm.h" +#include "message_parcel_mock.h" + +namespace OHOS { +namespace FileManagement { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::FileAccessFwk; + +class CloudDiskCommTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +public: + static inline std::shared_ptr messageParcelMock_ = nullptr; +}; + +void CloudDiskCommTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + messageParcelMock_ = std::make_shared(); + MessageParcelMock::messageParcel = messageParcelMock_; +} + +void CloudDiskCommTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + MessageParcelMock::messageParcel = nullptr; + messageParcelMock_ = nullptr; +} + +void CloudDiskCommTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CloudDiskCommTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: SyncFolder_Marshalling_001 + * @tc.desc: Test SyncFolder Marshalling success + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolder_Marshalling_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolder_Marshalling_001 start"; + + SyncFolder syncFolder("/test/path", State::ACTIVE, 100, "testDisplayName"); + MessageParcel parcel; + // Mock failed writes + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(false)); + bool result = syncFolder.Marshalling(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(false)); + result = syncFolder.Marshalling(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteUint32(_)).WillOnce(Return(false)); + result = syncFolder.Marshalling(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)).WillOnce(Return(false)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteUint32(_)).WillOnce(Return(true)); + result = syncFolder.Marshalling(parcel); + EXPECT_FALSE(result); + + // Mock successful writes + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteUint32(_)).WillOnce(Return(true)); + result = syncFolder.Marshalling(parcel); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "SyncFolder_Marshalling_001 end"; +} + +/** + * @tc.name: SyncFolder_ReadFromParcel_001 + * @tc.desc: Test SyncFolder ReadFromParcel success + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolder_ReadFromParcel_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolder_ReadFromParcel_001 start"; + SyncFolder syncFolder; + MessageParcel parcel; + + // Mock failure when reading path + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(false)); + bool result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce(Return(false)); + result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(-1), Return(true))); // -1: invalid state + result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::MAX_VALUE)), Return(true))); + result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + GTEST_LOG_(INFO) << "SyncFolder_ReadFromParcel_001 end"; +} + +/** + * @tc.name: SyncFolder_ReadFromParcel_002 + * @tc.desc: Test SyncFolder ReadFromParcel failure when reading path fails + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolder_ReadFromParcel_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolder_ReadFromParcel_002 start"; + SyncFolder syncFolder; + MessageParcel parcel; + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(false)); + bool result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)).WillOnce(Return(false)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + result = syncFolder.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + result = syncFolder.ReadFromParcel(parcel); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "SyncFolder_ReadFromParcel_002 end"; +} + +/** + * @tc.name: SyncFolder_Unmarshalling_001 + * @tc.desc: Test SyncFolder Unmarshalling + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolder_Unmarshalling_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolder_Unmarshalling_001 start"; + MessageParcel parcel; + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(false)); + SyncFolder *syncFolder = SyncFolder::Unmarshalling(parcel); + EXPECT_EQ(syncFolder, nullptr); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + syncFolder = SyncFolder::Unmarshalling(parcel); + EXPECT_NE(syncFolder, nullptr); + EXPECT_EQ(syncFolder->state_, State::INACTIVE); + if (syncFolder) { + delete syncFolder; + syncFolder = nullptr; + } + GTEST_LOG_(INFO) << "SyncFolder_Unmarshalling_001 end"; +} + +/** + * @tc.name: SyncFolderExt_Marshalling_001 + * @tc.desc: Test SyncFolderExt Marshalling + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolderExt_Marshalling_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolderExt_Marshalling_001 start"; + + SyncFolderExt syncFolderExt("/test/path", State::ACTIVE, 100, "testDisplayName", "testBundleName"); + MessageParcel parcel; + + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(false)); + bool result = syncFolderExt.Marshalling(parcel); + EXPECT_FALSE(result); + + // Mock failure when writing bundle name + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)) + .WillOnce(Return(true)).WillOnce(Return(false)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteUint32(_)).WillOnce(Return(true)); + result = syncFolderExt.Marshalling(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, WriteString(_)).WillOnce(Return(true)) + .WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteInt32(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, WriteUint32(_)).WillOnce(Return(true)); + result = syncFolderExt.Marshalling(parcel); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "SyncFolderExt_Marshalling_001 end"; +} + +/** + * @tc.name: SyncFolderExt_ReadFromParcel_001 + * @tc.desc: Test SyncFolderExt ReadFromParcel success + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolderExt_ReadFromParcel_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolderExt_ReadFromParcel_001 start"; + + SyncFolderExt syncFolderExt; + MessageParcel parcel; + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(false)); + bool result = syncFolderExt.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)) + .WillOnce(Return(true)).WillOnce(Return(false)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + result = syncFolderExt.ReadFromParcel(parcel); + EXPECT_FALSE(result); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)) + .WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + result = syncFolderExt.ReadFromParcel(parcel); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "SyncFolderExt_ReadFromParcel_001 end"; +} + +/** + * @tc.name: SyncFolderExt_Unmarshalling_001 + * @tc.desc: Test SyncFolderExt Unmarshalling success + * @tc.type: FUNC + */ +HWTEST_F(CloudDiskCommTest, SyncFolderExt_Unmarshalling_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SyncFolderExt_Unmarshalling_001 start"; + + MessageParcel parcel; + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(false)); + SyncFolderExt *syncFolderExt = SyncFolderExt::Unmarshalling(parcel); + EXPECT_EQ(syncFolderExt, nullptr); + + EXPECT_CALL(*messageParcelMock_, ReadString(_)).WillOnce(Return(true)) + .WillOnce(Return(true)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadInt32(_)).WillOnce( + DoAll(SetArgReferee<0>(static_cast(State::INACTIVE)), Return(true))); + EXPECT_CALL(*messageParcelMock_, ReadUint32(_)).WillOnce(Return(true)); + syncFolderExt = SyncFolderExt::Unmarshalling(parcel); + EXPECT_NE(syncFolderExt, nullptr); + EXPECT_EQ(syncFolderExt->state_, State::INACTIVE); + if (syncFolderExt) { + delete syncFolderExt; + syncFolderExt = nullptr; + } + GTEST_LOG_(INFO) << "SyncFolderExt_Unmarshalling_001 end"; +} +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cloud_disk_service_test.cpp b/test/unittest/cloud_disk_service_test.cpp new file mode 100644 index 00000000..74531256 --- /dev/null +++ b/test/unittest/cloud_disk_service_test.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 "file_access_service.h" + +#include +#include + +#include "notify_work_service.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::FileAccessFwk; +using namespace OHOS::FileManagement; + +namespace OHOS { +namespace FileAccessFwk { +class CloudDiskServiceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void CloudDiskServiceTest::SetUpTestCase(void) +{ + // Setup code to run before all tests +} + +void CloudDiskServiceTest::TearDownTestCase(void) +{ + // Teardown code to run after all tests +} + +void CloudDiskServiceTest::SetUp() +{ + // Setup code to run before each test +} + +void CloudDiskServiceTest::TearDown() +{ + // Teardown code to run after each test +} + +/** + * @tc.number: CloudDiskService_Register_001 + * @tc.name: Register cloud disk root info + * @tc.desc: Verify Register function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Register_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_Register_001"; + SyncFolder syncFolder; + syncFolder.path_ = "/storage/Users/currentUser"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Register(syncFolder); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_Register_001"; +} + +/** + * @tc.number: CloudDiskService_Unregister_001 + * @tc.name: Unregister cloud disk root info + * @tc.desc: Verify Unregister function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Unregister_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_Unregister_001"; + std::string path = "/storage/Users/currentUser"; + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Unregister(path); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_Unregister_001"; +} + +/** + * @tc.number: CloudDiskService_Active_001 + * @tc.name: Active cloud disk + * @tc.desc: Verify Active function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_Active_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_Active_001"; + std::string path = "/storage/Users/currentUser"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Active(path); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_Active_001"; +} + +/** + * @tc.number: CloudDiskService_InActive_001 + * @tc.name: Deactive cloud disk + * @tc.desc: Verify Deactive function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_InActive_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_InActive_001"; + std::string path = "/storage/Users/currentUser"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->Deactive(path); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_InActive_001"; +} + +/** + * @tc.number: CloudDiskService_GetSyncFolders_001 + * @tc.name: Get cloud disk roots + * @tc.desc: Verify GetSyncFolders function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_GetSyncFolders_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_GetSyncFolders_001"; + std::vector syncFolders; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->GetSyncFolders(syncFolders); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_GetSyncFolders_001"; +} + +/** + * @tc.number: CloudDiskService_GetAllSyncFolders_001 + * @tc.name: Get all cloud disk roots + * @tc.desc: Verify GetAllSyncFolders function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_GetAllSyncFolders_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_GetAllSyncFolders_001"; + std::vector syncFolderExts; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->GetAllSyncFolders(syncFolderExts); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_GetAllSyncFolders_001"; +} + +/** + * @tc.number: CloudDiskService_UpdateDisplayName_001 + * @tc.name: UpdateDisplayName function + * @tc.desc: Verify UpdateDisplayName function works correctly when NotifySyncFolderEvent returns true + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_UpdateDisplayName_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_UpdateDisplayName_001"; + std::string path = "/storage/Users/currentUser"; + std::string displayName = "TestDisplayName"; + + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + int32_t result = service->UpdateDisplayName(path, displayName); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_UpdateDisplayName_001"; +} + +/** + * @tc.number: CloudDiskService_IncreaseCnt_001 + * @tc.name: IncreaseCnt function + * @tc.desc: Verify IncreaseCnt function works correctly + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_IncreaseCnt_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_IncreaseCnt_001"; + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + + int32_t initialCount = service->calledCount_.load(); + service->IncreaseCnt("test_func"); + EXPECT_EQ(service->calledCount_.load(), initialCount + 1); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_IncreaseCnt_001"; +} + +/** + * @tc.number: CloudDiskService_DecreaseCnt_001 + * @tc.name: DecreaseCnt function + * @tc.desc: Verify DecreaseCnt function works correctly when count > 0 + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_DecreaseCnt_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_DecreaseCnt_001"; + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + + service->IncreaseCnt("test_func"); // Make sure count > 0 + int32_t initialCount = service->calledCount_.load(); + service->DecreaseCnt("test_func"); + EXPECT_EQ(service->calledCount_.load(), initialCount - 1); + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_DecreaseCnt_001"; +} + +/** + * @tc.number: CloudDiskService_DecreaseCnt_002 + * @tc.name: DecreaseCnt function + * @tc.desc: Verify DecreaseCnt function works correctly when count is 0 + */ +HWTEST_F(CloudDiskServiceTest, CloudDiskService_DecreaseCnt_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloudDiskServiceTest-begin CloudDiskService_DecreaseCnt_002"; + sptr service = FileAccessService::GetInstance(); + ASSERT_NE(service, nullptr); + + // Ensure count is 0 + service->calledCount_.store(0); + + int32_t initialCount = service->calledCount_.load(); + service->DecreaseCnt("test_func"); + EXPECT_EQ(service->calledCount_.load(), initialCount); // Should remain 0 + GTEST_LOG_(INFO) << "CloudDiskServiceTest-end CloudDiskService_DecreaseCnt_002"; +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/js_file_access_ext_ability_test.cpp b/test/unittest/js_file_access_ext_ability_test.cpp index a7a0b642..c1ed6dd7 100644 --- a/test/unittest/js_file_access_ext_ability_test.cpp +++ b/test/unittest/js_file_access_ext_ability_test.cpp @@ -82,6 +82,41 @@ int32_t FileAccessServiceBaseProxy::DisConnectFileExtAbility(const sptr &syncFolders) +{ + return ERR_OK; +} + +int32_t FileAccessServiceBaseProxy::GetAllSyncFolders(std::vector &syncFolderExts) +{ + return ERR_OK; +} + +int32_t FileAccessServiceBaseProxy::UpdateDisplayName(const std::string &path, const std::string &displayName) +{ + return ERR_OK; +} + void FileAccessExtAbility::Init(const std::shared_ptr &record, const std::shared_ptr &application, std::shared_ptr &handler, diff --git a/test/unittest/mock/file_access_service_mock.h b/test/unittest/mock/file_access_service_mock.h index 6e8f4492..3f27b1bb 100644 --- a/test/unittest/mock/file_access_service_mock.h +++ b/test/unittest/mock/file_access_service_mock.h @@ -42,6 +42,13 @@ public: MOCK_METHOD2(ConnectFileExtAbility, int32_t(const AAFwk::Want &want, const sptr& connection)); MOCK_METHOD1(DisConnectFileExtAbility, int32_t(const sptr& connection)); + MOCK_METHOD1(Register, int32_t(const SyncFolder &rootInfo)); + MOCK_METHOD1(Unregister, int32_t(const std::string &path)); + MOCK_METHOD1(Active, int32_t(const std::string &path)); + MOCK_METHOD1(Deactive, int32_t(const std::string &path)); + MOCK_METHOD1(GetSyncFolders, int32_t(std::vector &syncFolders)); + MOCK_METHOD1(GetAllSyncFolders, int32_t(std::vector &syncFolderExts)); + MOCK_METHOD2(UpdateDisplayName, int32_t(const std::string &path, const std::string &displayName)); }; } // namespace FileAccessFwk } // namespace OHOS diff --git a/test/unittest/mock/message_parcel_mock.cpp b/test/unittest/mock/message_parcel_mock.cpp index b1f73d73..f3ec2c42 100644 --- a/test/unittest/mock/message_parcel_mock.cpp +++ b/test/unittest/mock/message_parcel_mock.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 @@ -170,4 +170,12 @@ bool Parcel::ReadUint32(uint32_t &value) } return UMessageParcel::messageParcel->ReadUint32(value); } + +bool Parcel::WriteUint32(uint32_t value) +{ + if (UMessageParcel::messageParcel == nullptr) { + return false; + } + return UMessageParcel::messageParcel->WriteUint32(value); +} } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/mock/message_parcel_mock.h b/test/unittest/mock/message_parcel_mock.h index 9cff27dc..af2e8915 100644 --- a/test/unittest/mock/message_parcel_mock.h +++ b/test/unittest/mock/message_parcel_mock.h @@ -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 @@ -45,6 +45,7 @@ public: virtual int ReadFileDescriptor() = 0; virtual bool ReadStringVector(std::vector *value) = 0; virtual bool ReadUint32(uint32_t &value) = 0; + virtual bool WriteUint32(uint32_t value) = 0; public: static inline std::shared_ptr messageParcel = nullptr; }; @@ -69,6 +70,7 @@ public: MOCK_METHOD0(ReadFileDescriptor, int()); MOCK_METHOD1(ReadStringVector, bool(std::vector *value)); MOCK_METHOD1(ReadUint32, bool(uint32_t &value)); + MOCK_METHOD1(WriteUint32, bool(uint32_t value)); }; } // namespace OHOS::FileAccessFwk #endif // OHOS_FILEMGMT_UFS_MESSAGE_PARCEL_MOCK_H \ No newline at end of file diff --git a/test/unittest/notify_work_service_test.cpp b/test/unittest/notify_work_service_test.cpp new file mode 100644 index 00000000..4a043528 --- /dev/null +++ b/test/unittest/notify_work_service_test.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "notify_work_service.h" + +#include "cloud_disk_comm.h" +#include "hilog_wrapper.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::FileAccessFwk; +using namespace OHOS::FileManagement; + +namespace OHOS { +namespace FileAccessFwk { +class NotifyWorkServiceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void NotifyWorkServiceTest::SetUpTestCase(void) +{ + // Setup code to run before all tests +} + +void NotifyWorkServiceTest::TearDownTestCase(void) +{ + // Teardown code to run after all tests +} + +void NotifyWorkServiceTest::SetUp() +{ + // Setup code to run before each test +} + +void NotifyWorkServiceTest::TearDown() +{ + // Teardown code to run after each test +} + +/** + * @tc.number: NotifyWorkService_NotifySyncFolderEvent_001 + * @tc.name: NotifySyncFolderEvent_001 + * @tc.desc: Verify NotifySyncFolderEvent works + */ +HWTEST_F(NotifyWorkServiceTest, NotifyWorkService_NotifySyncFolderEvent_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-begin NotifyWorkService_NotifySyncFolderEvent_001"; + SyncFolderExt syncFolderExt; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + syncFolderExt.path_ = "data/storage"; + syncFolderExt.state_ = State::ACTIVE; + NotifyWorkService& service = NotifyWorkService::GetInstance(); + NotifyWorkService::EventType inValidEventType = + static_cast(-1); // -1: invalid EventType + bool result = service.NotifySyncFolderEvent(syncFolderExt, inValidEventType); + EXPECT_EQ(result, false); + + inValidEventType = NotifyWorkService::EventType::MAX_EVENT_TYPE; + result = service.NotifySyncFolderEvent(syncFolderExt, inValidEventType); + EXPECT_EQ(result, false); + + inValidEventType = + static_cast(5); // 5: invalid EventType + result = service.NotifySyncFolderEvent(syncFolderExt, inValidEventType); + EXPECT_EQ(result, false); + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-end NotifyWorkService_NotifySyncFolderEvent_001"; +} + +/** + * @tc.number: NotifyWorkService_NotifySyncFolderEvent_002 + * @tc.name: NotifySyncFolderEvent_002 + * @tc.desc: Verify NotifySyncFolderEvent works + */ +HWTEST_F(NotifyWorkServiceTest, NotifyWorkService_NotifySyncFolderEvent_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-begin NotifyWorkService_NotifySyncFolderEvent_002"; + SyncFolderExt syncFolderExt; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + syncFolderExt.path_ = "data/storage"; + syncFolderExt.state_ = State::ACTIVE; + syncFolderExt.displayNameResId_ = 0; // 0: Valid displayNameResId + NotifyWorkService& service = NotifyWorkService::GetInstance(); + bool result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::REGISTER); + EXPECT_EQ(result, true); + + syncFolderExt.displayName_ = ""; + result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::REGISTER); + EXPECT_EQ(result, true); + + syncFolderExt.displayName_ = "test"; + result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::REGISTER); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-end NotifyWorkService_NotifySyncFolderEvent_002"; +} + +/** + * @tc.number: NotifyWorkService_NotifySyncFolderEvent_003 + * @tc.name: NotifySyncFolderEvent_003 + * @tc.desc: Verify NotifySyncFolderEvent works + */ +HWTEST_F(NotifyWorkServiceTest, NotifyWorkService_NotifySyncFolderEvent_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-begin NotifyWorkService_NotifySyncFolderEvent_003"; + SyncFolderExt syncFolderExt; + syncFolderExt.bundleName_ = "com.example.simulatecloud"; + syncFolderExt.path_ = "data/storage"; + syncFolderExt.state_ = State::ACTIVE; + syncFolderExt.displayNameResId_ = 1; // 1: test displayNameResId + NotifyWorkService& service = NotifyWorkService::GetInstance(); + bool result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::UNREGISTER); + EXPECT_EQ(result, true); + + syncFolderExt.displayName_ = ""; + result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::REGISTER); + EXPECT_EQ(result, true); + + syncFolderExt.displayName_ = "test"; + result = service.NotifySyncFolderEvent(syncFolderExt, NotifyWorkService::EventType::REGISTER); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "NotifyWorkServiceTest-end NotifyWorkService_NotifySyncFolderEvent_003"; +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/utils/file_access_framework_errno.h b/utils/file_access_framework_errno.h index cc11ccbb..7eedadb2 100644 --- a/utils/file_access_framework_errno.h +++ b/utils/file_access_framework_errno.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 @@ -28,6 +28,7 @@ const int ERR_URI = 13900002; const int ERR_NOT_DIR = 13900018; const int ERR_IS_DIR = 13900019; const int BASE_OFFSET = 14300001; +const int CLOUD_DISK_BASE_OFFSET = 34400001; enum { ERR_OK = 0, E_IPCS = BASE_OFFSET, // IPC error @@ -46,7 +47,25 @@ enum { E_DO_NOT_HAVE_PARENT, // Do not have parent uri in observerNode E_LOAD_SA, // load SA failed E_PERMISSION = 201, // Permission verification failed - E_PERMISSION_SYS // is not system app + E_PERMISSION_SYS, // is not system app + + E_NOT_SUPPORT = 801, + E_SERVICE_DIED = 29189, + + // cloud disk errcode + E_INVALID_PARAM = CLOUD_DISK_BASE_OFFSET, // Invalid parameter + E_PERSIST_SYNC_FOLDER_FAILED, // Failed to persist Sync folder + E_IPC_FAILED, // IPC error + E_SYNC_FOLDER_LIMIT_EXCEEDED, // Sync folder limit exceeded + E_SYNC_FOLDER_CONFLICT_SELF, // Conflict with own app's Sync folder + E_SYNC_FOLDER_CONFLICT_OTHER, // Conflict with other app's Sync folder + E_CREATE_SYNC_FOLDER_FAILED, // Failed to create Sync folder + E_SYNC_FOLDER_NOT_REGISTERED, // Sync folder not registered + E_REMOVE_SYNC_FOLDER_FAILED, // Failed to remove Sync folder + E_UPDATE_SYNC_FOLDER_FAILED, // Failed to update Sync folder properties + E_SYNC_FOLDER_NOT_EXIST, // Sync folder not exist + E_INTERNAL_ERROR = CLOUD_DISK_BASE_OFFSET + 15, // Internal error 15: offset + E_SYSTEM_RESTRICTED, // System restricted }; } // namespace FileAccessFwk } // namespace OHOS -- Gitee