From 620e8908476b3883f09241a7001eeb2b66cb7270 Mon Sep 17 00:00:00 2001 From: yaoruozi Date: Wed, 10 Sep 2025 11:53:38 +0800 Subject: [PATCH] clean syncfolder Signed-off-by: yaoruozi --- services/5010.json | 17 +- services/BUILD.gn | 18 + services/file_access_service.para | 14 + services/ile_access_service.para.dac | 14 + .../include/bundle_observer.h | 47 ++ .../include/file_access_service.h | 20 +- .../src/bundle_observer.cpp | 133 ++++++ .../src/file_access_service.cpp | 81 +++- test/unittest/BUILD.gn | 66 +++ test/unittest/bundle_observer_test.cpp | 322 ++++++++++++++ test/unittest/file_access_service_test.cpp | 418 ++++++++++++++++++ test/unittest/mock/file_access_service_mock.h | 10 + .../system_ability_manager_client_mock.cpp | 33 ++ .../mock/system_ability_manager_client_mock.h | 46 ++ 14 files changed, 1224 insertions(+), 15 deletions(-) create mode 100644 services/file_access_service.para create mode 100644 services/ile_access_service.para.dac create mode 100644 services/native/file_access_service/include/bundle_observer.h create mode 100644 services/native/file_access_service/src/bundle_observer.cpp create mode 100644 test/unittest/bundle_observer_test.cpp create mode 100644 test/unittest/file_access_service_test.cpp create mode 100644 test/unittest/mock/system_ability_manager_client_mock.cpp create mode 100644 test/unittest/mock/system_ability_manager_client_mock.h diff --git a/services/5010.json b/services/5010.json index 8f40348d..dd7e0070 100755 --- a/services/5010.json +++ b/services/5010.json @@ -6,7 +6,22 @@ "libpath": "libfile_access_service.z.so", "run-on-create": false, "distributed": false, - "dump_level": 1 + "dump_level": 1, + "cache-common-event":true, + "start-on-demand": { + "commonevent": [ + { + "name": "usual.event.PACKAGE_REMOVED", + "conditions": [ + { + "eventId": "param", + "name": "persist.clouddiskmanager.workstatus", + "value": "true" + } + ] + } + ] + } } ] } \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index b269f07e..28c830ec 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -183,6 +183,7 @@ ohos_shared_library("file_access_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", + "native/file_access_service/src/bundle_observer.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", @@ -197,6 +198,8 @@ ohos_shared_library("file_access_service") { ":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", + ":file_access_service.para", + ":file_access_service.para.dac", ] external_deps = [ @@ -220,3 +223,18 @@ ohos_shared_library("file_access_service") { subsystem_name = "filemanagement" part_name = "user_file_service" } + +ohos_prebuilt_etc("file_access_service.para") { + source = "file_access_service.para" + part_name = "user_file_service" + module_install_dir = "etc/param" + subsystem_name = "filemanagement" +} + +ohos_prebuilt_etc("file_access_service.para.dac") { + source = "file_access_service.para.dac" + part_name = "user_file_service" + module_install_dir = "etc/param" + subsystem_name = "filemanagement" +} + diff --git a/services/file_access_service.para b/services/file_access_service.para new file mode 100644 index 00000000..adecb4f4 --- /dev/null +++ b/services/file_access_service.para @@ -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. + +persist.clouddiskmanager.workstatus = true \ No newline at end of file diff --git a/services/ile_access_service.para.dac b/services/ile_access_service.para.dac new file mode 100644 index 00000000..efa13ef4 --- /dev/null +++ b/services/ile_access_service.para.dac @@ -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. + +persist.clouddiskmanager.workstatus = file_manager:file_manager:0776 \ No newline at end of file diff --git a/services/native/file_access_service/include/bundle_observer.h b/services/native/file_access_service/include/bundle_observer.h new file mode 100644 index 00000000..6f9810df --- /dev/null +++ b/services/native/file_access_service/include/bundle_observer.h @@ -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. + */ + +#ifndef BUNDLE_OBSERVER_H +#define BUNDLE_OBSERVER_H + +#include +#include +#include + +#include "common_event_subscribe_info.h" +#include "common_event_subscriber.h" +#include "system_ability_ondemand_reason.h" + + +namespace OHOS { +namespace FileAccessFwk { +using namespace std; + +class BundleObserver final: public EventFwk::CommonEventSubscriber { +public: + BundleObserver() = default; + ~BundleObserver(); + + static int32_t HandleBundleBroadcast(); + static int32_t ClearSyncFolder(const string &bundleName, int32_t userId, int32_t appIndex); + static string GetValueByKey(const std::map &map, const string &key); + static int32_t GetNumberFromString(const string &str, const int32_t defaultValue); + + explicit BundleObserver(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + virtual void OnReceiveEvent(const EventFwk::CommonEventData &data) override; +} +} // namespace FileAccessFwk +} // namespace OHOS +#endif // BUNDLE_OBSERVER_H \ No newline at end of file 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 143cc854..963e0148 100644 --- a/services/native/file_access_service/include/file_access_service.h +++ b/services/native/file_access_service/include/file_access_service.h @@ -24,14 +24,18 @@ #include #include -#include "file_access_helper.h" +#include "bundle_observer.h" #include "bundle_mgr_interface.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "file_access_helper.h" #include "file_access_ext_connection.h" #include "file_access_service_base_stub.h" #include "ifile_access_ext_base.h" #include "holder_manager.h" #include "ifile_access_ext_base.h" #include "iremote_object.h" +#include "thread_pool.h" #include "timer.h" #include "uri.h" #include "want.h" @@ -223,12 +227,16 @@ public: bool CheckCallingPermission(const std::string &permission); static sptr GetInstance(); void Init(); - virtual ~FileAccessService() = default; + ~FileAccessService(); virtual void OnStart() override; + virtual void OnStart(const SystemAbilityOnDemandReason &startReason) override; virtual void OnStop() override; + + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; int32_t Dump(int32_t fd, const std::vector &args) override; - + void DisconnectAppProxy(const sptr& connection); void RemoveAppProxy(const sptr& connection); @@ -320,6 +328,12 @@ private: std::unordered_map> appProxyMap_; std::unordered_map> appConnection_; sptr appDeathRecipient_; + + void RegisterBundleBroadcast(); + void UnRegisterBundleBroadcast(); + + static inline std::shared_ptr bundleObserver_ = nullptr; + OHOS::ThreadPool handleBroadCastThreadPool_; std::atomic calledCount_{0}; std::mutex calledMutex_; }; diff --git a/services/native/file_access_service/src/bundle_observer.cpp b/services/native/file_access_service/src/bundle_observer.cpp new file mode 100644 index 00000000..1f8e7611 --- /dev/null +++ b/services/native/file_access_service/src/bundle_observer.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "bundle_observer.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "hilog_wrapper.h" +#include "iservice_registry.h" +#include "notify_work_service.h" +#include "system_ability_definition.h" +#include "ufs_db_services_constants.h" +#include "ufs_rdb_adapter.h" + +namespace OHOS { +namespace FileAccessFwk { + +const int32_t SA_ID = 5010; +const int32_t APP_DEFAULT_INDEX = 0; +const int32_t USER_ID_DEFAULT = 100; + +BundleObserver::BundleObserver(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + :CommonEventSubscriber(subscribeInfo) +{ +} + +BundleObserver::~BundleObserver() +{ +} + +int32_t BundleObserver::HandleBundleBroadcast() +{ + HILOG_INFO("HandleBundleBroadcast Begin"); + auto saMgrPtr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgrPtr == nullptr){ + HILOG_ERROR("saMgrPtr is nullptr"); + return ERR_INVALID_VALUE; + } + std::vector extraDataIdList; + int32_t ret = saMgrPtr->GetCommonEventExtraDataIdList(SA_ID, extraDataIdList, + EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + if (ret != ERR_OK) { + HILOG_ERROR("GetCommonEventExtraDataIdList failed, ret = %{public}d", ret); + return ret; + } + for (auto dataId : extraDataIdList) { + MessageParcel dataParcel; + int32_t getDataRet = saMgrPtr->GetOnDemandReasonExtraData(dataId, dataParcel); + if (getDataRet != ERR_OK) { + HILOG_ERROR("GetOnDemandReasonExtraData failed, ret = %{public}d", getDataRet); + continue; + } + auto extraData = dataParcel.ReadParcelable(); + if (extraData == nullptr) { + HILOG_ERROR("extraData is nullptr"); + continue; + } + map want = extraData->GetWant(); + string userIdStr = GetValueByKey(want, "userId"); + string bundleName = GetValueByKey(want, "bundleName"); + string appIndexStr = GetValueByKey(want, "appIndex"); + int32_t appIndex = GetNumberFromString(appIndexStr, APP_DEFAULT_INDEX); + int32_t userId = GetNumberFromString(userIdStr, USER_ID_DEFAULT); + ClearSyncFolder(bundleName, userId, appIndex); + } + return ERR_OK; +} + +int32_t BundleObserver::ClearSyncFolder(const string &bundleName, int32_t userId, int32_t appIndex) +{ + HILOG_INFO("Begin ClearSyncRoot, bundleName: %{public}s, userId: %{public}d, appIndex: %{public}d", + bundleName.c_str(), userId, appIndex); + auto fileAccessService = FileAccessService::GetInstance(); + if (fileAccessService == nullptr) { + HILOG_ERROR("FileAccessService is nullptr"); + return ERR_INVALID_VALUE; + } + int32_t ret = fileAccessService->UnregisterAllByBundle(bundleName, userId, appIndex); + if (ret != ERR_OK) { + HILOG_ERROR("UnregisterAllByBundle failed, ret = %{public}d", ret); + return ret; + } + return ERR_OK; +} + +void BundleObserver::OnReceiveEvent(const EventFwk::CommonEventData &data) +{ + HILOG_INFO("BundleObserver::OnReceiveEvent start"); + const OHOS::AAFwk::Want want = data.GetWant(); + string action = want.GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) { + OHOS::AAFwk::WantParams params = want.GetParams(); + int32_t userId = params.GetIntParam("userId", USER_ID_DEFAULT); + std::string bundleName = want.GetStringParam("bundleName"); + int32_t appIndex = params.GetIntParam("appIndex", APP_DEFAULT_INDEX); + int32_t ret = ClearSyncFolder(bundleName, userId, appIndex); + if (ret != 0) { + HILOG_ERROR("BundleObserver::OnReceiveEvent ClearSyncRoot failed, ret:%{public}d", ret); + return; + } + } +} + +std::string BundleObserver::GetValueByKey(const std::map &map, const string &key) +{ + auto it = map.find(key); + if (it != map.end()) { + return it->second; + } + return ""; +} + +int32_t BundleObserver::GetNumberFromString(const string &str, const int32_t defaultValue) +{ + if (str.empty()) { + HILOG_ERROR("transform failed, str is empty"); + return defaultValue; + } + return static_cast(std::atoi(str.c_str())); +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file 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 49b311e2..490077c6 100644 --- a/services/native/file_access_service/src/file_access_service.cpp +++ b/services/native/file_access_service/src/file_access_service.cpp @@ -18,17 +18,21 @@ #include #include -#include "user_access_tracer.h" +#include "access_token.h" +#include "accesstken_kit.h" +#include "common_event_manager.h" +#include "common_event_support.h" + #include "file_access_framework_errno.h" #include "file_access_extension_info.h" +#include "file_access_framework_errno.h" #include "hilog_wrapper.h" #include "hitrace_meter.h" #include "ipc_skeleton.h" -#include "system_ability_definition.h" #include "iservice_registry.h" +#include "system_ability_definition.h" #include "uri_ext.h" -#include "access_token.h" -#include "accesstoken_kit.h" +#include "user_access_tracer.h" using namespace std; namespace OHOS { @@ -47,6 +51,7 @@ constexpr int32_t NOTIFY_TIME_INTERVAL = 500; constexpr int32_t MAX_WAIT_TIME = 20; constexpr int32_t ONE_SECOND = 1 * 1000; constexpr int32_t UNLOAD_SA_WAIT_TIME = 30; +constexpr int32_t THREAD_NUM = 1; std::vector deviceUris(DEVICE_ROOTS.begin(), DEVICE_ROOTS.end()); bool FileAccessService::CheckCallingPermission(const std::string &permission) @@ -82,19 +87,20 @@ sptr FileAccessService::GetInstance() FileAccessService::FileAccessService() : SystemAbility(FILE_ACCESS_SERVICE_ID, false) { + handleBroadCastThreadPool_.Start(THREAD_NUM); +} + +FileAccessService::~FileAccessService() +{ + handleBroadCastThreadPool_.Stop(); } void FileAccessService::OnStart() { UserAccessTracer trace; trace.Start("OnStart"); - sptr service = FileAccessService::GetInstance(); - if (service == nullptr) { - HILOG_ERROR("service is nullptr"); - return; - } - service->Init(); - if (!Publish(service)) { + Init(); + if (!Publish(this)) { HILOG_ERROR("OnStart register to system ability manager failed"); return; } @@ -724,6 +730,7 @@ void FileAccessService::InitTimer() HILOG_ERROR("UnloadSA, GetSystemAbilityManager is null."); return; } + UnRegisterBundleBroadcast(); int32_t result = saManager->UnloadSystemAbility(FILE_ACCESS_SERVICE_ID); if (result != ERR_OK) { HILOG_ERROR("UnloadSA, UnloadSystemAbility result: %{public}d", result); @@ -906,5 +913,57 @@ void FileAccessService::AppDeathRecipient::OnRemoteDied(const wptrRemoveAppProxy(remoteBroker); } + +void FileAccessService::OnStart(const SystemAbilityOnDemandReason &startReason) +{ + HILOG_INFO("FileAccessService::OnStart"); + AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); + if (startReason.HasExtraData()) { + auto task = [this, startReason]() { + BundleObserver::HandleBundleBroadcast(); + }; + handleBroadCastThreadPool_.AddTask(task); + } + OnStart(); +} + +void FileAccessService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + HILOG_INFO("FileAccessService::OnAddSystemAbility Begin"); + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + if (bundleObserver_ == nullptr) { + HILOG_ERROR("OnAddSystemAbility, bundleObserver is null, Will register bundle broadcast"); + RegisterBundleBroadcast(); + } + } +} + +void FileAccessService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + HILOG_INFO("FileAccessService::OnRemoveSystemAbility"); +} + + +void FileAccessService::RegisterBundleBroadcast() +{ + HILOG_INFO("FileAccessService::RegisterBundleBroadcast Begin"); + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills); + bundleObserver_ = std::make_shared(subscriberInfo); + EventFwk::CommonEventManager::NewSubscribeCommonEvent(bundleObserver_); + HILOG_INFO("FileAccessService::RegisterBundleBroadcast End"); +} + +void FileAccessService::UnRegisterBundleBroadcast() +{ + HILOG_INFO("FileAccessService::UnRegisterBundleBroadcast Begin"); + if (bundleObserver_ == nullptr) { + HILOG_ERROR("UnRegisterBundleBroadcast error, bundleObserver is null"); + return; + } + int32_t ret = EventFwk::CommonEventManager::NewUnSubscribeCommonEventSync(bundleObserver_); + HILOG_INFO("FileAccessService::UnRegisterBundleBroadcast End. ret = %{public}d", ret); +} } // namespace FileAccessFwk } // namespace OHOS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 64ddccaf..1aa9f97c 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -527,6 +527,71 @@ ohos_unittest("cloud_disk_comm_test") { testonly = true } +ohos_unittest("file_access_service_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 = [ + "file_access_service_test.cpp", + "bundle_observer_test.cpp", + "mock/file_access_service_mock.h", + "mock/system_ability_manager_client_mock.cpp", + ] + + include_dirs = [ + "${user_file_service_path}/interfaces/inner_api/file_access/include", + "${user_file_service_path}/services/native/file_access_service/include", + "mock", + ] + + configs = [ "//build/config/compiler:exceptions" ] + + deps = [ + "${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", + "${user_file_service_path}/services:file_access_service", + "${user_file_service_path}/services:file_access_service_base_source", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:app_manager", + "ability_runtime:runtime", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_core", + "cJSON:cjson_static", + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:rpc", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "selinux_adapter:librestorecon", + ] + + defines = [ + "private=public", + "protected=public", + + ] +} + group("user_file_service_unit_test") { testonly = true @@ -537,6 +602,7 @@ group("user_file_service_unit_test") { ":external_file_access_management_test", ":external_file_access_notify_test", ":file_access_ext_stub_impl_test", + ":file_access_service_test", ":js_file_access_ext_ability_test", ":notify_work_service_test", ":urie_test", diff --git a/test/unittest/bundle_observer_test.cpp b/test/unittest/bundle_observer_test.cpp new file mode 100644 index 00000000..16b970e5 --- /dev/null +++ b/test/unittest/bundle_observer_test.cpp @@ -0,0 +1,322 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "bundle_observer.h" +#include "common_event_data.h" +#include "common_event_support.h" +#include "if_system_ability_manager_mock.h" +#include "system_ability_manager_client_mock.h" +#include "want.h" +#include "system_ability_ondemand_reason.h" +#include "iservice_registry.h" +#include "if_system_ability_manager.h" + +namespace OHOS { +namespace FileAccessFwk { +using namespace testing; +using namespace testing::ext; + +class BundleObserverTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + static inline std::shared_ptr saMgrClient_ = nullptr; + static inline std::shared_ptr saMgr_ = nullptr; + static inline std::shared_ptr smc_ = nullptr; +}; + +void BundleObserverTest::SetUpTestCase() +{ + saMgrClient_ = std::make_shared(); + saMgr_ = sptr(new ISystemAbilityManagerMock()); + smc_ = std::make_shared(); + UfsSystemAbilityManagerClientMock::instance_ = smc; +} + +void BundleObserverTest::TearDownTestCase() +{ + saMgrClient_ = nullptr; + saMgr_ = nullptr; + smc_ = nullptr; + UfsSystemAbilityManagerClientMock::instance_ = nullptr; +} + +void BundleObserverTest::SetUp() +{ +} + +void BundleObserverTest::TearDown() +{ +} + +/** + * @tc.name: BundleObserverConstructorTest + * @tc.desc: Test BundleObserver constructor + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverConstructorTest, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverConstructorTest start"; + EventFwk::CommonEventSubscribeInfo subscribeInfo; + BundleObserver observer(subscribeInfo); + GTEST_LOG_(INFO) << "BundleObserverConstructorTest end"; +} + +/** + * @tc.name: BundleObserverHandleBundleBroadcastTest001 + * @tc.desc: Test HandleBundleBroadcast when SystemAbilityManager is null + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverHandleBundleBroadcastTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest001 start"; + int32_t result = BundleObserver::HandleBundleBroadcast(); + EXPECT_EQ(result, ERR_INVALID_VALUE); + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest001 end"; +} + +/** + * @tc.name: BundleObserverHandleBundleBroadcastTest002 + * @tc.desc: Test HandleBundleBroadcast when GetCommonEventExtraDataIdList fails + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverHandleBundleBroadcastTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest002 start"; + auto saMrgInfo = sptr(new ISystemAbilityManagerMock()); + EXPECT_CALL(*smc_, GetSystemAbilityManager()).WillOnce(testing::Return(saMrgInfo)); + EXPECT_CALL(*saMrgInfo, GetCommonEventExtraDataIdlist(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(ERR_FLATTEN_OBJECT)); + int32_t result = BundleObserver::HandleBundleBroadcast(); + EXPECT_EQ(result, ERR_FLATTEN_OBJECT); + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest002 end"; +} + +/** + * @tc.name: BundleObserverHandleBundleBroadcastTest003 + * @tc.desc: Test HandleBundleBroadcast when GetCommonEventExtraDataIdList success + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverHandleBundleBroadcastTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest003 start"; + auto saMrgInfo = sptr(new ISystemAbilityManagerMock()); + EXPECT_CALL(*smc_, GetSystemAbilityManager()).WillOnce(testing::Return(saMrgInfo)); + std::vector extraDataIds; + int64_t dataId1 = 1; + int64_t dataId2 = 2; + extraDataIds.push_back(1); + extraDataIds.push_back(2); + map want; + std::string bundleName = "com.example.demo"; + want.emplace("bundleName", bundleName); + want.emplace("userId", "100"); + want.emplace("appIndex", "0"); + EXPECT_CALL(*saMrgInfo, GetCommonEventExtraDataIdlist(testing::_, testing::_, testing::_)) + .WillOnce(DoAll(SetArgReferee<1>(extraDataIds)), testing::Return(0)); + EXPECT_CALL(*saMrgInfo, GetOnDemandReasonExtraData(dataId1, testing::_)) + .WillOnce(testing::Return(ERR_FLATTEN_OBJECT)); + EXPECT_CALL(*saMrgInfo, GetOnDemandReasonExtraData(dataId2, testing::_)) + .WillOnce(testing::Return(0)); + int32_t result = BundleObserver::HandleBundleBroadcast(); + EXPECT_EQ(result, ERR_OK); + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest003 end"; +} + +/** + * @tc.name: BundleObserverClearSyncFolderTest001 + * @tc.desc: Test ClearSyncFolder with empty sync folders + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverClearSyncFolderTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest001 start"; + std::string bundleName = "test.bundle"; + int32_t userId = 100; + int32_t appIndex = 0; + int32_t result = BundleObserver::ClearSyncFolder(bundleName, userId, appIndex); + EXPECT_EQ(result, ERR_INVALID_VALUE); + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest001 end"; +} + +/** + * @tc.name: BundleObserverClearSyncFolderTest002 + * @tc.desc: Test ClearSyncFolder with non-empty sync folders + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverClearSyncFolderTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest002 start"; + std::string bundleName = "test.bundle"; + int32_t userId = 100; + int32_t appIndex = 0; + int32_t result = BundleObserver::ClearSyncFolder(bundleName, userId, appIndex); + EXPECT_EQ(result, ERR_INVALID_VALUE); + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest002 end"; +} + +/** + * @tc.name: BundleObserverClearSyncFolderTest003 + * @tc.desc: Test ClearSyncFolder with non-empty sync folders and successful deletion + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverClearSyncFolderTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest003 start"; + // This test would require mocking SynchronousRootManager and NotifyWorkerService + // Since these are not easily mockable in the current setup, we'll focus on the logic flow + std::string bundleName = "test.bundle"; + int32_t userId = 100; + int32_t appIndex = 0; + int32_t result = BundleObserver::ClearSyncFolder(bundleName, userId, appIndex); + // In real implementation, this would depend on the mocked behavior of SynchronousRootManager + // For now, we expect it to return ERR_INVALID_VALUE because we can't easily mock the dependencies + EXPECT_EQ(result, ERR_INVALID_VALUE); + GTEST_LOG_(INFO) << "BundleObserverClearSyncFolderTest003 end"; +} + +/** + * @tc.name: BundleObserverOnReceiveEventTest001 + * @tc.desc: Test OnReceiveEvent with package removed event + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverOnReceiveEventTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverOnReceiveEventTest001 start"; + EventFwk::CommonEventSubscribeInfo subscribeInfo; + BundleObserver observer(subscribeInfo); + + EventFwk::CommonEventData data; + OHOS::AAFwk::Want want; + want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + + std::string bundleName = "com.example.test"; + want.SetParam("userId", 100); + want.SetParam("bundleName", bundleName); + want.SetParam("appIndex", 0); + data.SetWant(want); + observer.OnReceiveEvent(data); + GTEST_LOG_(INFO) << "BundleObserverOnReceiveEventTest001 end"; +} + +/** + * @tc.name: BundleObserverOnReceiveEventTest002 + * @tc.desc: Test OnReceiveEvent with other event + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverOnReceiveEventTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverOnReceiveEventTest002 start"; + EventFwk::CommonEventSubscribeInfo subscribeInfo; + BundleObserver observer(subscribeInfo); + + EventFwk::CommonEventData data; + OHOS::AAFwk::Want want; + want.SetAction("other_event"); + data.SetWant(want); + + observer.OnReceiveEvent(data); + GTEST_LOG_(INFO) << "BundleObserverOnReceiveEventTest002 end"; +} + +/** + * @tc.name: BundleObserverGetValueByKeyTest001 + * @tc.desc: Test GetValueByKey with existing key + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverGetValueByKeyTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverGetValueByKeyTest001 start"; + std::map testMap; + testMap["key1"] = "value1"; + testMap["key2"] = "value2"; + + std::string result = BundleObserver::GetValueByKey(testMap, "key1"); + EXPECT_EQ(result, "value1"); + GTEST_LOG_(INFO) << "BundleObserverGetValueByKeyTest001 end"; +} + +/** + * @tc.name: BundleObserverGetValueByKeyTest002 + * @tc.desc: Test GetValueByKey with non-existing key + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverGetValueByKeyTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverGetValueByKeyTest002 start"; + std::map testMap; + testMap["key1"] = "value1"; + testMap["key2"] = "value2"; + + std::string result = BundleObserver::GetValueByKey(testMap, "key3"); + EXPECT_EQ(result, ""); + GTEST_LOG_(INFO) << "BundleObserverGetValueByKeyTest002 end"; +} + +/** + * @tc.name: BundleObserverGetNumberFromStringTest001 + * @tc.desc: Test GetNumberFromString with valid string + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverGetNumberFromStringTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest001 start"; + std::string testStr = "123"; + int32_t defaultValue = 0; + + int32_t result = BundleObserver::GetNumberFromString(testStr, defaultValue); + EXPECT_EQ(result, 123); + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest001 end"; +} + +/** + * @tc.name: BundleObserverGetNumberFromStringTest002 + * @tc.desc: Test GetNumberFromString with empty string + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverGetNumberFromStringTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest002 start"; + std::string testStr = ""; + int32_t defaultValue = 100; + + int32_t result = BundleObserver::GetNumberFromString(testStr, defaultValue); + EXPECT_EQ(result, 100); + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest002 end"; +} + +/** + * @tc.name: BundleObserverGetNumberFromStringTest003 + * @tc.desc: Test GetNumberFromString with invalid string + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverGetNumberFromStringTest003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest003 start"; + std::string testStr = "abc"; + int32_t defaultValue = 100; + + int32_t result = BundleObserver::GetNumberFromString(testStr, defaultValue); + EXPECT_EQ(result, 0); + GTEST_LOG_(INFO) << "BundleObserverGetNumberFromStringTest003 end"; +} +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/file_access_service_test.cpp b/test/unittest/file_access_service_test.cpp new file mode 100644 index 00000000..f5299c9c --- /dev/null +++ b/test/unittest/file_access_service_test.cpp @@ -0,0 +1,418 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "file_access_service.h" +#include "file_access_service_mock.h" +#include "file_access_ext_connection.h" +#include "file_access_framework_errno.h" +#include "uri.h" +#include "want.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "system_ability_definition.h" +#include "ipc_skeleton.h" +#include "message_parcel.h" +#include "message_option.h" +#include "iremote_object.h" +#include "ifile_access_ext_base.h" +#include "file_access_extension_info.h" + +namespace OHOS { +namespace FileAccessFwk { +using namespace testing; +using namespace testing::ext; + +class FileAccessServiceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static void SetNativeToken(); + static sptr service_; + static std::shared_ptr serviceMock_; +}; + +sptr FileAccessServiceTest::service_ = nullptr; +std::shared_ptr FileAccessServiceTest::serviceMock_ = nullptr; + +void FileAccessServiceTest::SetUpTestCase() +{ + SetNativeToken(); + service_ = FileAccessService::GetInstance(); + ASSERT_NE(service_, nullptr); + serviceMock_ = std::make_shared(); +} + +void FileAccessServiceTest::TearDownTestCase() +{ + service_ = nullptr; + serviceMock_ = nullptr; +} + +void FileAccessServiceTest::SetUp() +{ +} + +void FileAccessServiceTest::TearDown() +{ +} + +void FileAccessServiceTest::SetNativeToken() +{ + uint64_t tokenId; + const char *perms[] = { + "ohos.permission.FILE_ACCESS_MANAGER", + "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + "ohos.permission.CONNECT_FILE_ACCESS_EXTENSION" + }; + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 3, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "file_access_service_test", + .aplStr = "system_basic", + }; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); +} + +/** + * @tc.name: GetInstanceTest + * @tc.desc: Test get instance of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetInstanceTest, TestSize.Level1) +{ + auto instance = FileAccessService::GetInstance(); + EXPECT_NE(instance, nullptr); +} + +/** + * @tc.name: OnStartTest + * @tc.desc: Test OnStart method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnStartTest, TestSize.Level1) +{ + service_->OnStart(); + EXPECT_TRUE(service_->IsServiceReady()); +} + +/** + * @tc.name: OnStopTest + * @tc.desc: Test OnStop method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnStopTest, TestSize.Level1) +{ + service_->OnStop(); + // Note: This test just verifies the method can be called without crashing + // Reset the service state after test + service_->OnStart(); +} + +/** + * @tc.name: CheckCallingPermissionTest + * @tc.desc: Test CheckCallingPermission method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, CheckCallingPermissionTest, TestSize.Level1) +{ + std::string permission = "ohos.permission.FILE_ACCESS_MANAGER"; + bool result = service_->CheckCallingPermission(permission); + EXPECT_TRUE(result); +} + +/** + * @tc.name: IsServiceReadyTest + * @tc.desc: Test IsServiceReady method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, IsServiceReadyTest, TestSize.Level1) +{ + service_->OnStart(); + bool ready = service_->IsServiceReady(); + EXPECT_TRUE(ready); +} + +/** + * @tc.name: ConnectFileExtAbilityTest + * @tc.desc: Test ConnectFileExtAbility method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, ConnectFileExtAbilityTest, TestSize.Level1) +{ + AAFwk::Want want; + sptr connection = nullptr; + int32_t result = service_->ConnectFileExtAbility(want, connection); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: DisConnectFileExtAbilityTest + * @tc.desc: Test DisConnectFileExtAbility method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, DisConnectFileExtAbilityTest, TestSize.Level1) +{ + sptr connection = nullptr; + int32_t result = service_->DisConnectFileExtAbility(connection); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: RegisterNotifyTest + * @tc.desc: Test RegisterNotify method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, RegisterNotifyTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + bool notifyForDescendants = true; + sptr observer = nullptr; + ConnectExtensionInfo info; + int32_t result = service_->RegisterNotify(uri, notifyForDescendants, observer, info); + EXPECT_EQ(result, E_PERMISSION); +} + +/** + * @tc.name: UnregisterNotifyTest + * @tc.desc: Test UnregisterNotify method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, UnregisterNotifyTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + sptr observer = nullptr; + ConnectExtensionInfo info; + int32_t result = service_->UnregisterNotify(uri, observer, info); + EXPECT_EQ(result, E_PERMISSION); +} + +/** + * @tc.name: UnregisterNotifyNoObserverTest + * @tc.desc: Test UnregisterNotifyNoObserver method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, UnregisterNotifyNoObserverTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + ConnectExtensionInfo info; + int32_t result = service_->UnregisterNotifyNoObserver(uri, info); + EXPECT_EQ(result, E_PERMISSION); +} + +/** + * @tc.name: OnChangeTest + * @tc.desc: Test OnChange method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnChangeTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + NotifyType notifyType = NotifyType::NOTIFY_INSERT; + int32_t result = service_->OnChange(uri, notifyType); + EXPECT_EQ(result, E_PERMISSION); +} + +/** + * @tc.name: GetExtensionProxyTest + * @tc.desc: Test GetExtensionProxy method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetExtensionProxyTest, TestSize.Level1) +{ + ConnectExtensionInfo info; + sptr extensionProxy = nullptr; + int32_t result = service_->GetExtensionProxy(info, extensionProxy); + EXPECT_EQ(result, E_PERMISSION); +} + +/** + * @tc.name: IsUnusedTest + * @tc.desc: Test IsUnused method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, IsUnusedTest, TestSize.Level1) +{ + bool result = service_->IsUnused(); + // This will depend on the current state, but shouldn't crash + EXPECT_FALSE(result); // Since we have active connections +} + +/** + * @tc.name: FindExtProxyByBundleNameTest + * @tc.desc: Test FindExtProxyByBundleName method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, FindExtProxyByBundleNameTest, TestSize.Level1) +{ + std::string bundleName = "com.example.data"; + sptr result = service_->FindExtProxyByBundleName(bundleName); + // Should return nullptr since we haven't registered any extensions + EXPECT_EQ(result, nullptr); +} + +/** + * @tc.name: AddExtProxyInfoTest + * @tc.desc: Test AddExtProxyInfo method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, AddExtProxyInfoTest, TestSize.Level1) +{ + std::string bundleName = "com.test.bundle"; + sptr extProxy = nullptr; + // This should not crash + service_->AddExtProxyInfo(bundleName, extProxy); + // Verify the proxy was added + sptr result = service_->FindExtProxyByBundleName(bundleName); + EXPECT_EQ(result, extProxy); +} + +/** + * @tc.name: OnStartWithReasonTest + * @tc.desc: Test OnStart with SystemAbilityOnDemandReason method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnStartWithReasonTest, TestSize.Level1) +{ + SystemAbilityOnDemandReason startReason; + // This test just verifies the method can be called without crashing + // In a real scenario, this would trigger HandleBundleBroadcast in a separate thread + service_->OnStart(startReason); +} + +/** + * @tc.name: OnAddSystemAbilityTest + * @tc.desc: Test OnAddSystemAbility method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnAddSystemAbilityTest, TestSize.Level1) +{ + // Test with COMMON_EVENT_SERVICE_ID + service_->OnAddSystemAbility(COMMON_EVENT_SERVICE_ID, ""); + // Should register bundle broadcast + EXPECT_NE(service_->bundleObserver_, nullptr); +} + +/** + * @tc.name: OnRemoveSystemAbilityTest + * @tc.desc: Test OnRemoveSystemAbility method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OnRemoveSystemAbilityTest, TestSize.Level1) +{ + // Test with COMMON_EVENT_SERVICE_ID when bundleObserver_ is not null + service_->OnRemoveSystemAbility(COMMON_EVENT_SERVICE_ID, ""); +} + +/** + * @tc.name: RegisterBundleBroadcastTest + * @tc.desc: Test RegisterBundleBroadcast method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, RegisterBundleBroadcastTest, TestSize.Level1) +{ + // Save current bundleObserver_ + auto oldObserver = service_->bundleObserver_; + + // Register new bundle broadcast + service_->RegisterBundleBroadcast(); + + // Should have a bundle observer now + EXPECT_NE(service_->bundleObserver_, nullptr); + + // Restore original observer + service_->bundleObserver_ = oldObserver; +} + +/** + * @tc.name: UnRegisterBundleBroadcastTest + * @tc.desc: Test UnRegisterBundleBroadcast method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, UnRegisterBundleBroadcastTest, TestSize.Level1) +{ + // Save current bundleObserver_ + auto oldObserver = service_->bundleObserver_; + + // Create a mock bundle observer for testing + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills); + auto testObserver = std::make_shared(subscriberInfo); + service_->bundleObserver_ = testObserver; + + // Unregister bundle broadcast + service_->UnRegisterBundleBroadcast(); + + // Restore original observer + service_->bundleObserver_ = oldObserver; +} + +/** + * @tc.name: GetInstanceDoubleCallTest + * @tc.desc: Test double call to GetInstance method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetInstanceDoubleCallTest, TestSize.Level1) +{ + auto instance1 = FileAccessService::GetInstance(); + auto instance2 = FileAccessService::GetInstance(); + EXPECT_EQ(instance1, instance2); +} + +/** + * @tc.name: InitTest + * @tc.desc: Test Init method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, InitTest, TestSize.Level1) +{ + // Call Init method + service_->Init(); + + // Check that death recipients are created + EXPECT_NE(service_->extensionDeathRecipient_, nullptr); + EXPECT_NE(service_->observerDeathRecipient_, nullptr); + EXPECT_NE(service_->appDeathRecipient_, nullptr); +} + +/** + * @tc.name: DumpTest + * @tc.desc: Test Dump method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, DumpTest, TestSize.Level1) +{ + int32_t fd = 1; + std::vector args; + int32_t result = service_->Dump(fd, args); + EXPECT_EQ(result, ERR_OK); +} + +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/mock/file_access_service_mock.h b/test/unittest/mock/file_access_service_mock.h index 3f27b1bb..f357c0b9 100644 --- a/test/unittest/mock/file_access_service_mock.h +++ b/test/unittest/mock/file_access_service_mock.h @@ -17,6 +17,7 @@ #define FILE_ACCESS_SERVICE_MOCK_H #include "file_access_service_base_stub.h" +#include "file_access_service.h" namespace OHOS { namespace FileAccessFwk { @@ -42,6 +43,15 @@ public: MOCK_METHOD2(ConnectFileExtAbility, int32_t(const AAFwk::Want &want, const sptr& connection)); MOCK_METHOD1(DisConnectFileExtAbility, int32_t(const sptr& connection)); + + // FileAccessService specific methods + MOCK_METHOD0(OnStart, void()); + MOCK_METHOD0(OnStop, void()); + MOCK_METHOD2(CheckCallingPermission, bool(const std::string &permission, int32_t tokenId)); + MOCK_METHOD0(IsServiceReady, bool()); + MOCK_METHOD3(RegisterUriObserver, int32_t(const Uri &uri, const sptr &observer, bool notifyForDescendants)); + MOCK_METHOD2(UnregisterUriObserver, int32_t(const Uri &uri, const sptr &observer)); + MOCK_METHOD1(UnregisterUriObserverWithoutObserver, int32_t(const Uri &uri)); 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)); diff --git a/test/unittest/mock/system_ability_manager_client_mock.cpp b/test/unittest/mock/system_ability_manager_client_mock.cpp new file mode 100644 index 00000000..d1d9fc56 --- /dev/null +++ b/test/unittest/mock/system_ability_manager_client_mock.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "system_ability_manager_client_mock.h" + +namespace OHOS { +namespace FileAccessFwk { +SystemAbilityManagerClient& SystemAbilityManagerClient::GetInstance() +{ + static auto instance = std::make_shared(); + return *instance; +} + +sptr SystemAbilityManagerClientMock::GetSystemAbilityManager() +{ + if (UfsSystemAbilityManagerClient::instance == nullptr) { + UfsSystemAbilityManagerClient::instance = std::make_shared(); + } + return UfsSystemAbilityManagerClient::instance->GetSystemAbilityManager(); +} +} \ No newline at end of file diff --git a/test/unittest/mock/system_ability_manager_client_mock.h b/test/unittest/mock/system_ability_manager_client_mock.h new file mode 100644 index 00000000..9254d7fc --- /dev/null +++ b/test/unittest/mock/system_ability_manager_client_mock.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 OHOS_FILEMGMT_UFS_SYSTEM_ABILITY_MANAGER_CLIENT_MOCK_H +#define OHOS_FILEMGMT_UFS_SYSTEM_ABILITY_MANAGER_CLIENT_MOCK_H + + +#include "" +#include "iservice_registry.h" +#include "if_system_ability_manager_mock.h" + +namespace OHOS { +namespace FileAccessFwk { +class UfsSystemAbilityManagerClient { +public: + virtual sptr GetSystemAbilityManager() = 0; + +public: + UfsSystemAbilityManagerClient() = default; + virtual ~UfsSystemAbilityManagerClient() = default; + static inline std::shared_ptr instance_ = nullptr; +}; + +class UfsSystemAbilityManagerClientMock : public UfsSystemAbilityManagerClient { +public: + UfsSystemAbilityManagerClientMock() = default; + virtual ~UfsSystemAbilityManagerClientMock() = default; +public: + MOCK_METHOD0(GetSystemAbilityManager, sptr()); +}; +} // namespace FileAccessFwk { +} + + -- Gitee