From a8cb9b27e92e963249128b80bb1593c3aafc1994 Mon Sep 17 00:00:00 2001 From: "yaoruozi1@huawei.com" Date: Tue, 19 Aug 2025 16:31:38 +0800 Subject: [PATCH] test UT Signed-off-by: yaoruozi1@huawei.com --- services/5010.json | 16 +- services/BUILD.gn | 18 + services/file_access_service.para | 14 + services/ile_access_service.para.dac | 14 + .../include/bundle_observer.h | 44 ++ .../include/file_access_service.h | 13 +- .../src/bundle_observer.cpp | 68 +++ .../src/file_access_service.cpp | 74 ++- test/unittest/BUILD.gn | 60 +++ test/unittest/bundle_observer_test.cpp | 157 ++++++ test/unittest/file_access_service_test.cpp | 484 ++++++++++++++++++ .../mock/file_access_service_mock.cpp | 23 + test/unittest/mock/file_access_service_mock.h | 31 ++ 13 files changed, 1002 insertions(+), 14 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/file_access_service_mock.cpp diff --git a/services/5010.json b/services/5010.json index 8f40348d..5ae6dff4 100755 --- a/services/5010.json +++ b/services/5010.json @@ -6,7 +6,21 @@ "libpath": "libfile_access_service.z.so", "run-on-create": false, "distributed": false, - "dump_level": 1 + "dump_level": 1, + "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 d0441abd..89cc3f0c 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -180,6 +180,7 @@ ohos_shared_library("file_access_service") { shlib_type = "sa" sources = [ "${user_file_service_path}/interfaces/inner_api/file_access/src/uri_ext.cpp", + "native/file_access_service/src/bundle_observer.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", @@ -192,6 +193,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 = [ @@ -214,3 +217,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..2bf27f8c --- /dev/null +++ b/services/native/file_access_service/include/bundle_observer.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + + #ifndef BUNDLE_OBSERVER_H + #define BUNDLE_OBSERVER_H + + #include + #include + #include + + #include "common_event_subscriber_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(const SystemAbilityOnDemandReason &startReason); + static int32_t ClearSyncRoot(const string &userId); + + explicit BundleObserver(const EventFwk::CommonEventSubscribeInfo &subscribeInfo); + virtual void OnReceiveEvent(const EventFwk::CommonEventData &data) override; +} +} // namespace FileAccessFwk +} // namespace OHOS \ 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 b24e0c47..70341236 100644 --- a/services/native/file_access_service/include/file_access_service.h +++ b/services/native/file_access_service/include/file_access_service.h @@ -32,6 +32,7 @@ #include "holder_manager.h" #include "ifile_access_ext_base.h" #include "iremote_object.h" +#include "bundle_observer.h" #include "timer.h" #include "uri.h" #include "want.h" @@ -226,9 +227,13 @@ public: virtual ~FileAccessService() = default; virtual void OnStart() override; + virtual void OnStart(const SystemAbilityOnDemandReason &startReason) override; virtual void OnStop() override; + + void OnAddSystemAbility(uint32_t systemAbilityId, const std::string &deviceId) override; + void OnRemoveSystemAbility(uint32_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); @@ -298,7 +303,7 @@ private: HolderManager> obsManager_; std::mutex mapMutex_; std::unordered_map> cMap_; - + class AppDeathRecipient : public IRemoteObject::DeathRecipient { public: AppDeathRecipient() {} @@ -310,6 +315,10 @@ private: std::unordered_map> appProxyMap_; std::unordered_map> appConnection_; sptr appDeathRecipient_; + + static inline std::shared_ptr bundleObserver_ = nullptr; + void RegisterBundleBroadcast(); + void UnRegisterBundleBroadcast(); }; } // namespace FileAccessFwk } // namespace OHOS 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..3f215f30 --- /dev/null +++ b/services/native/file_access_service/src/bundle_observer.cpp @@ -0,0 +1,68 @@ +/* + * 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 "bundle_observer.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace FileAccessFwk { + +BundleObserver::BundleObserver(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + :CommonEventSubscriber(subscribeInfo) +{ +} + +BundleObserver::~BundleObserver() +{ +} + +int32_t BundleObserver::HandleBundleBroadcast(const SystemAbilityOnDemandReason &startReason) +{ + HILOG_INFO("BundleObserver::HandleBundleBroadcast start"); + map want = startReason.GetWant(); + if (want.find("userId") == want.end()) { + HILOG_ERROR("BundleObserver::HandleBundleBroadcast userId not found"); + return ERR_INVALID_VALUE; + } + return ClearSyncRoot(want["userId"]); +} + +int32_t BundleObserver::ClearSyncRoot(const string &userId) +{ + +} + +int32_t 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", -1); + + int32_t ret = ClearSyncRoot(std::to_string(userId)); + if (ret != 0) { + HILOG_ERROR("BundleObserver::OnReceiveEvent ClearSyncRoot failed"); + } + + } + +} + +} +} \ 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 e87c99cf..37555262 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 { @@ -88,13 +92,13 @@ 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)) { + // sptr service = FileAccessService::GetInstance(); + // if (service == nullptr) { + // HILOG_ERROR("service is nullptr"); + // return; + // } + this->Init(); + if (!Publish(this)) { HILOG_ERROR("OnStart register to system ability manager failed"); return; } @@ -724,6 +728,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); @@ -907,5 +912,52 @@ 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()) { + std::thread([this, startReason]() { + BundleObserver::HandleBundleBroadcast(startReason); + }).detach(); + } + OnStart(); +} + +void FileAccessService::OnAddSystemAbility(uint32_t systemAbilityId, const std::string & deviceId) +{ + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + if (bundleObserver_ == nullptr) { + RegisterBundleBroadcast(); + } + } +} + +void FileAccessService::OnRemoveSystemAbility(uint32_t systemAbilityId, const std::string & deviceId) +{ + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + if (bundleObserver_ != nullptr) { + return; + } + } +} + + +void FileAccessService::RegisterBundleBroadcast() +{ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills); + obsManager_ = std::make_shared(subscriberInfo); + EventFwk::CommonEventManager::NewSubscribeCommonEvent(obsManager_); +} + +void FileAccessService::UnRegisterBundleBroadcast() +{ + if (obsManager_ != nullptr) { + EventFwk::CommonEventManager::NewUnSubscribeCommonEventSync(obsManager_); + } +} + } // namespace FileAccessFwk } // namespace OHOS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 1e41b55e..b48a8b91 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -371,6 +371,65 @@ ohos_unittest("urie_test") { defines = [ "private=public" ] } +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", + ] + + 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", + "samgr:samgr_proxy", + "selinux_adapter:librestorecon", + ] + + defines = [ "private=public" ] +} + group("user_file_service_unit_test") { testonly = true @@ -380,6 +439,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", ":urie_test", ] diff --git a/test/unittest/bundle_observer_test.cpp b/test/unittest/bundle_observer_test.cpp new file mode 100644 index 00000000..bed88aeb --- /dev/null +++ b/test/unittest/bundle_observer_test.cpp @@ -0,0 +1,157 @@ +/* + * 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 "want.h" +#include "system_ability_ondemand_reason.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; +}; + +void BundleObserverTest::SetUpTestCase() +{ +} + +void BundleObserverTest::TearDownTestCase() +{ +} + +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 with valid userId + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverHandleBundleBroadcastTest001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest001 start"; + SystemAbilityOnDemandReason startReason; + // TODO: Add proper test implementation when ClearSyncRoot is implemented + // int32_t result = BundleObserver::HandleBundleBroadcast(startReason); + // EXPECT_EQ(result, ERR_INVALID_VALUE); // As userId is not set + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest001 end"; +} + +/** + * @tc.name: BundleObserverHandleBundleBroadcastTest002 + * @tc.desc: Test HandleBundleBroadcast with invalid userId + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverHandleBundleBroadcastTest002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest002 start"; + SystemAbilityOnDemandReason startReason; + // Add userId to the want map + // TODO: Add proper test implementation when ClearSyncRoot is implemented + // int32_t result = BundleObserver::HandleBundleBroadcast(startReason); + // EXPECT_EQ(result, 0); // Assuming success + GTEST_LOG_(INFO) << "BundleObserverHandleBundleBroadcastTest002 end"; +} + +/** + * @tc.name: BundleObserverClearSyncRootTest + * @tc.desc: Test ClearSyncRoot function + * @tc.type: FUNC + */ +HWTEST_F(BundleObserverTest, BundleObserverClearSyncRootTest, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BundleObserverClearSyncRootTest start"; + // TODO: Add proper test implementation when ClearSyncRoot is implemented + // std::string userId = "100"; + // int32_t result = BundleObserver::ClearSyncRoot(userId); + // EXPECT_EQ(result, 0); + GTEST_LOG_(INFO) << "BundleObserverClearSyncRootTest 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); + // TODO: Set userId in want params for complete testing + data.SetWant(want); + + // TODO: Add proper test implementation when ClearSyncRoot is implemented + // 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"; +} + +} // 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..77d7620f --- /dev/null +++ b/test/unittest/file_access_service_test.cpp @@ -0,0 +1,484 @@ +/* + * 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: GetRootsTest + * @tc.desc: Test GetRoots method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetRootsTest, TestSize.Level1) +{ + std::vector rootInfoVec; + int32_t result = service_->GetRoots(rootInfoVec); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: GetFileInfoFromUriTest + * @tc.desc: Test GetFileInfoFromUri method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetFileInfoFromUriTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + FileInfo fileInfo; + int32_t result = service_->GetFileInfoFromUri(uri, fileInfo); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: GetFileInfoFromRelativePathTest + * @tc.desc: Test GetFileInfoFromRelativePath method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, GetFileInfoFromRelativePathTest, TestSize.Level1) +{ + std::string uriStr = "file://com.example.data/storage/Users"; + FileInfo fileInfo; + int32_t result = service_->GetFileInfoFromRelativePath(uriStr, fileInfo); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: OpenFileTest + * @tc.desc: Test OpenFile method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, OpenFileTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + int mode = 0; + int fd = -1; + int32_t result = service_->OpenFile(uri, mode, fd); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: CreateFileTest + * @tc.desc: Test CreateFile method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, CreateFileTest, TestSize.Level1) +{ + Uri parentUri("file://com.example.data/storage"); + std::string name = "test.txt"; + Uri newUri(""); + int32_t result = service_->CreateFile(parentUri, name, newUri); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: CreateDirectoryTest + * @tc.desc: Test CreateDirectory method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, CreateDirectoryTest, TestSize.Level1) +{ + Uri parentUri("file://com.example.data/storage"); + std::string name = "testDir"; + Uri newUri(""); + int32_t result = service_->CreateDirectory(parentUri, name, newUri); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: DeleteTest + * @tc.desc: Test Delete method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, DeleteTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/test.txt"); + bool recursive = false; + int32_t result = service_->Delete(uri, recursive); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: MoveTest + * @tc.desc: Test Move method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, MoveTest, TestSize.Level1) +{ + Uri sourceUri("file://com.example.data/storage/test.txt"); + Uri destUri("file://com.example.data/storage/dest/test.txt"); + int32_t result = service_->Move(sourceUri, destUri); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: RenameTest + * @tc.desc: Test Rename method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, RenameTest, TestSize.Level1) +{ + Uri sourceUri("file://com.example.data/storage/test.txt"); + std::string displayName = "newName.txt"; + int32_t result = service_->Rename(sourceUri, displayName); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: MkDirTest + * @tc.desc: Test MkDir method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, MkDirTest, TestSize.Level1) +{ + Uri parentUri("file://com.example.data/storage"); + std::string name = "newDir"; + Uri newUri(""); + int32_t result = service_->MkDir(parentUri, name, newUri); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: ListFileTest + * @tc.desc: Test ListFile method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, ListFileTest, TestSize.Level1) +{ + Uri parentUri("file://com.example.data/storage"); + std::vector fileInfoVec; + int32_t result = service_->ListFile(parentUri, fileInfoVec); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: ScanFileTest + * @tc.desc: Test ScanFile method of FileAccessService + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, ScanFileTest, TestSize.Level1) +{ + Uri parentUri("file://com.example.data/storage"); + std::vector fileInfoVec; + int32_t result = service_->ScanFile(parentUri, fileInfoVec); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: MockGetRootsTest + * @tc.desc: Test mock GetRoots method + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, MockGetRootsTest, TestSize.Level1) +{ + std::vector rootInfoVec; + EXPECT_CALL(*serviceMock_, GetRoots(testing::_)) + .WillOnce(testing::Return(ERR_OK)); + int32_t result = serviceMock_->GetRoots(rootInfoVec); + EXPECT_EQ(result, ERR_OK); +} + +/** + * @tc.name: MockGetFileInfoFromUriTest + * @tc.desc: Test mock GetFileInfoFromUri method + * @tc.type: FUNC + */ +HWTEST_F(FileAccessServiceTest, MockGetFileInfoFromUriTest, TestSize.Level1) +{ + Uri uri("file://com.example.data/storage/Users"); + FileInfo fileInfo; + EXPECT_CALL(*serviceMock_, GetFileInfoFromUri(testing::_, testing::_)) + .WillOnce(testing::Return(ERR_OK)); + int32_t result = serviceMock_->GetFileInfoFromUri(uri, fileInfo); + 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); +} + +} // namespace FileAccessFwk +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/mock/file_access_service_mock.cpp b/test/unittest/mock/file_access_service_mock.cpp new file mode 100644 index 00000000..d737f661 --- /dev/null +++ b/test/unittest/mock/file_access_service_mock.cpp @@ -0,0 +1,23 @@ +/* + * 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 "file_access_service_mock.h" +#include + +namespace OHOS { +namespace FileAccessFwk { + +} +} diff --git a/test/unittest/mock/file_access_service_mock.h b/test/unittest/mock/file_access_service_mock.h index 6e8f4492..72215c69 100644 --- a/test/unittest/mock/file_access_service_mock.h +++ b/test/unittest/mock/file_access_service_mock.h @@ -17,6 +17,14 @@ #define FILE_ACCESS_SERVICE_MOCK_H #include "file_access_service_base_stub.h" +#include "file_access_service.h" +#include "uri.h" +#include "file_info.h" +#include "root_info.h" +#include "file_access_extension_info.h" +#include "want.h" +#include "iability_connection.h" +#include "ifile_access_ext_base.h" namespace OHOS { namespace FileAccessFwk { @@ -42,6 +50,29 @@ 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_METHOD1(GetRoots, int32_t(std::vector &rootInfoVec)); + MOCK_METHOD2(GetFileInfoFromUri, int32_t(const Uri &uri, FileInfo &fileInfo)); + MOCK_METHOD2(GetFileInfoFromRelativePath, int32_t(const std::string &uri, FileInfo &fileInfo)); + MOCK_METHOD3(OpenFile, int32_t(const Uri &uri, const int &mode, int &fd)); + MOCK_METHOD3(CreateFile, int32_t(const Uri &parentUri, const std::string &name, Uri &newUri)); + MOCK_METHOD3(CreateDirectory, int32_t(const Uri &parentUri, const std::string &name, Uri &newUri)); + MOCK_METHOD2(Delete, int32_t(const Uri &uri, bool recursive)); + MOCK_METHOD2(Move, int32_t(const Uri &sourceUri, const Uri &destUri)); + MOCK_METHOD2(Rename, int32_t(const Uri &sourceUri, const std::string &displayName)); + MOCK_METHOD3(MkDir, int32_t(const Uri &parentUri, const std::string &name, Uri &newUri)); + MOCK_METHOD2(ListFile, int32_t(const Uri &parentUri, std::vector &fileInfoVec)); + MOCK_METHOD2(ScanFile, int32_t(const Uri &parentUri, std::vector &fileInfoVec)); + 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_METHOD2(ConnectExtension, sptr(Uri &uri, const std::shared_ptr &info)); + MOCK_METHOD1(FindExtProxyByBundleName, sptr(std::string bundleName)); }; } // namespace FileAccessFwk } // namespace OHOS -- Gitee