diff --git a/frameworks/c/ability_runtime/BUILD.gn b/frameworks/c/ability_runtime/BUILD.gn index 94f46fa9d2..a959d32ddf 100644 --- a/frameworks/c/ability_runtime/BUILD.gn +++ b/frameworks/c/ability_runtime/BUILD.gn @@ -88,6 +88,7 @@ ohos_shared_library("ability_runtime") { "ability_base:ability_base_want", "ability_base:want", "c_utils:utils", + "eventhandler:libeventhandler", "ffrt:libffrt", "hilog:libhilog", "image_framework:image_native", diff --git a/frameworks/c/ability_runtime/src/modular_object_extension_context.cpp b/frameworks/c/ability_runtime/src/modular_object_extension_context.cpp index c3d7eae8eb..690bb272cf 100644 --- a/frameworks/c/ability_runtime/src/modular_object_extension_context.cpp +++ b/frameworks/c/ability_runtime/src/modular_object_extension_context.cpp @@ -15,9 +15,13 @@ #include "modular_object_extension_context.h" +#include +#include + #include "ability_business_error_utils.h" #include "ability_manager_client.h" #include "hilog_tag_wrapper.h" +#include "ipc_error_code.h" #include "modular_object_extension_context_impl.h" #include "modular_object_extension_types.h" #include "start_options_impl.h" @@ -29,6 +33,16 @@ using namespace OHOS::AAFwk; using namespace OHOS::AbilityRuntime; namespace { +constexpr const char *REQUEST_TASK_NAME = "ModObjExtRequest"; +constexpr const char *DESTROY_TASK_NAME = "ModObjExtDestroy"; + +struct IPCRemoteStubUserData { + std::weak_ptr handler; + OH_OnRemoteRequestCallback requestCallback = nullptr; + OH_OnRemoteDestroyCallback destroyCallback = nullptr; + void *userData = nullptr; +}; + AbilityRuntime_ErrorCode CheckMoeContext(OH_AbilityRuntime_ModObjExtensionContextHandle context, std::shared_ptr &contextPtr) { @@ -62,6 +76,67 @@ AbilityRuntime_ErrorCode TransformWant(const AbilityBase_Want *want, Want &abili } return ABILITY_RUNTIME_ERROR_CODE_NO_ERROR; } + +std::unique_ptr CreateIPCRemoteStubUserData( + const std::shared_ptr &handler, + OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, + void *userData) +{ + std::unique_ptr callbackInfo(new (std::nothrow) IPCRemoteStubUserData()); + if (callbackInfo == nullptr) { + return nullptr; + } + callbackInfo->handler = handler; + callbackInfo->requestCallback = requestCallback; + callbackInfo->destroyCallback = destroyCallback; + callbackInfo->userData = userData; + return callbackInfo; +} + +int OnRemoteRequestOnHandler(uint32_t code, const OHIPCParcel *data, OHIPCParcel *reply, void *userData) +{ + auto *callbackInfo = static_cast(userData); + if (callbackInfo == nullptr || callbackInfo->requestCallback == nullptr) { + return OH_IPC_INNER_ERROR; + } + auto handler = callbackInfo->handler.lock(); + if (handler == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "event handler not exist"); + return OH_IPC_INNER_ERROR; + } + int32_t result = OH_IPC_INNER_ERROR; + auto task = [&callbackInfo, &result, code, data, reply]() { + result = callbackInfo->requestCallback(code, data, reply, callbackInfo->userData); + }; + if (!handler->PostSyncTask(task, REQUEST_TASK_NAME)) { + TAG_LOGE(AAFwkTag::APPKIT, "post request task failed"); + return OH_IPC_INNER_ERROR; + } + return result; +} + +void OnRemoteDestroyOnHandler(void *userData) +{ + std::unique_ptr callbackInfo(static_cast(userData)); + if (callbackInfo == nullptr) { + return; + } + if (callbackInfo->destroyCallback == nullptr) { + return; + } + auto handler = callbackInfo->handler.lock(); + if (handler == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "event handler not exist"); + return; + } + auto task = [&callbackInfo]() { + callbackInfo->destroyCallback(callbackInfo->userData); + }; + if (!handler->PostSyncTask(task, DESTROY_TASK_NAME)) { + TAG_LOGE(AAFwkTag::APPKIT, "post destroy task failed"); + return; + } +} } // namespace #ifdef __cplusplus @@ -138,6 +213,43 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf( return ConvertToCommonBusinessErrorCode(err); } +OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor, + OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData) +{ + if (descriptor == nullptr || requestCallback == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "invalid create stub params"); + return nullptr; + } + std::shared_ptr contextPtr; + auto ret = CheckMoeContext(context, contextPtr); + if (ret != ABILITY_RUNTIME_ERROR_CODE_NO_ERROR) { + return nullptr; + } + auto moeContext = std::static_pointer_cast(contextPtr); + auto callbackInfo = CreateIPCRemoteStubUserData( + moeContext->GetEventHandler(), requestCallback, destroyCallback, userData); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create callback info failed"); + return nullptr; + } + auto *stub = OH_IPCRemoteStub_Create(descriptor, OnRemoteRequestOnHandler, + OnRemoteDestroyOnHandler, callbackInfo.get()); + if (stub == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create remote stub failed"); + return nullptr; + } + callbackInfo.release(); + return stub; +} + +void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub) +{ + (void)context; + OH_IPCRemoteStub_Destroy(stub); +} + #ifdef __cplusplus } // extern "C" #endif diff --git a/frameworks/native/ability/native/modular_object_extension/modular_object_extension.cpp b/frameworks/native/ability/native/modular_object_extension/modular_object_extension.cpp index 13793c1e73..04cfc7eec6 100644 --- a/frameworks/native/ability/native/modular_object_extension/modular_object_extension.cpp +++ b/frameworks/native/ability/native/modular_object_extension/modular_object_extension.cpp @@ -17,6 +17,7 @@ #include +#include "ability_handler.h" #include "hilog_tag_wrapper.h" #include "ipc_inner_object.h" #include "native_runtime.h" @@ -53,6 +54,7 @@ void ModularObjectExtension::Init(const std::shared_ptr &rec moeContext_->type = AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT; auto context = GetContext(); if (context != nullptr) { + context->SetEventHandler(std::static_pointer_cast(handler)); moeContext_->context = context->weak_from_this(); } moeInstance_->context = moeContext_; diff --git a/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp b/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp index d639a4b347..5d9b286247 100644 --- a/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp +++ b/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp @@ -24,6 +24,17 @@ namespace AbilityRuntime { const size_t ModularObjectExtensionContext::CONTEXT_TYPE_ID( std::hash {} ("ModularObjectExtensionContext")); +void ModularObjectExtensionContext::SetEventHandler( + const std::shared_ptr &handler) +{ + handler_ = handler; +} + +std::shared_ptr ModularObjectExtensionContext::GetEventHandler() const +{ + return handler_.lock(); +} + ErrCode ModularObjectExtensionContext::StartSelfUIAbility(const AAFwk::Want &want) const { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/interfaces/kits/c/ability_runtime/modular_object_extension_context.h b/interfaces/kits/c/ability_runtime/modular_object_extension_context.h index bd4f2ae372..897d16d8a2 100644 --- a/interfaces/kits/c/ability_runtime/modular_object_extension_context.h +++ b/interfaces/kits/c/ability_runtime/modular_object_extension_context.h @@ -157,6 +157,41 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbi AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf( OH_AbilityRuntime_ModObjExtensionContextHandle context); +/** + * @brief Creates an OHIPCRemoteStub object with callbacks running on the extension's designated thread. + * The requestCallback and destroyCallback are invoked serially on the thread determined by the + * extension's {@link OH_AbilityRuntime_ThreadMode}. After calling + * {@link OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub}, no new requestCallback + * invocations will occur, and any in-flight requestCallback will complete before destroyCallback is invoked. + * + * The caller is responsible for destroying the returned object by calling + * {@link OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub} to avoid memory leaks. + * + * @param context Represents a pointer to a modular object extension ability context. + * @param descriptor Pointer to the descriptor of the OHIPCRemoteStub object to create. It cannot be NULL. + * The string is copied internally during creation, so the caller may release the descriptor + * after this function returns. + * @param requestCallback Callback used to process the data request. It cannot be NULL. + * @param destroyCallback Callback to be invoked when the object is destroyed. It can be NULL. + * @param userData Pointer to the user data. It can be NULL. Must remain valid before the object is destroyed. + * @return Returns the pointer to the OHIPCRemoteStub object created if the operation is successful; + * returns NULL otherwise. + * @since 26.0.0 + */ +OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor, + OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData); + +/** + * @brief Destroys an OHIPCRemoteStub object. + * + * @param context Represents a pointer to a modular object extension ability context. + * @param stub Pointer to the OHIPCRemoteStub object to destroy. + * @since 26.0.0 + */ +void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub); + #ifdef __cplusplus } #endif diff --git a/interfaces/kits/native/ability/native/modular_object_extension/modular_object_extension_context_impl.h b/interfaces/kits/native/ability/native/modular_object_extension/modular_object_extension_context_impl.h index 9b53861c0e..baff3582db 100644 --- a/interfaces/kits/native/ability/native/modular_object_extension/modular_object_extension_context_impl.h +++ b/interfaces/kits/native/ability/native/modular_object_extension/modular_object_extension_context_impl.h @@ -16,6 +16,9 @@ #ifndef OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H #define OHOS_ABILITY_RUNTIME_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H +#include + +#include "event_handler.h" #include "extension_context.h" #include "start_options.h" #include "want.h" @@ -27,6 +30,10 @@ public: ModularObjectExtensionContext() = default; ~ModularObjectExtensionContext() override = default; + void SetEventHandler(const std::shared_ptr &handler); + + std::shared_ptr GetEventHandler() const; + ErrCode StartSelfUIAbility(const AAFwk::Want &want) const; ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const; @@ -40,6 +47,9 @@ protected: { return contextTypeId == CONTEXT_TYPE_ID || ExtensionContext::IsContext(contextTypeId); } + +private: + std::weak_ptr handler_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 614e8824e6..c4339930f1 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -352,6 +352,7 @@ group("unittest") { "modular_object_ability_connection_test:unittest", "modular_object_extension_context_capi_test:unittest", "modular_object_extension_test:unittest", + "modular_object_extension_context_impl_event_handler_test:unittest", "modular_object_extension_context_impl_test:unittest", "data_ability_manager_test:unittest", "data_ability_observer_proxy_test:unittest", diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cparcel.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cparcel.h index f2220d18c0..d99a427425 100644 --- a/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cparcel.h +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cparcel.h @@ -16,6 +16,10 @@ #ifndef MOCK_IPC_CPARCEL_H #define MOCK_IPC_CPARCEL_H +struct OHIPCParcel { + int dummy; +}; + struct OHIPCRemoteStub { int dummy; }; diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cremote_object.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cremote_object.h new file mode 100644 index 0000000000..15a9b46e39 --- /dev/null +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_cremote_object.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_IPC_CREMOTE_OBJECT_H +#define MOCK_IPC_CREMOTE_OBJECT_H + +#include + +#include "ipc_cparcel.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*OH_OnRemoteRequestCallback)(uint32_t code, const OHIPCParcel *data, + OHIPCParcel *reply, void *userData); +typedef void (*OH_OnRemoteDestroyCallback)(void *userData); + +OHIPCRemoteStub* OH_IPCRemoteStub_Create(const char *descriptor, OH_OnRemoteRequestCallback requestCallback, + OH_OnRemoteDestroyCallback destroyCallback, void *userData); +void OH_IPCRemoteStub_Destroy(OHIPCRemoteStub *stub); + +#ifdef __cplusplus +} +#endif + +#endif // MOCK_IPC_CREMOTE_OBJECT_H \ No newline at end of file diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_error_code.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_error_code.h new file mode 100644 index 0000000000..0b4e1359dd --- /dev/null +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/ipc_error_code.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_IPC_ERROR_CODE_H +#define MOCK_IPC_ERROR_CODE_H + +constexpr int OH_IPC_INNER_ERROR = -1; + +#endif // MOCK_IPC_ERROR_CODE_H \ No newline at end of file diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/mock_types.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/mock_types.h index 7e2fc0f38e..71985cad4b 100644 --- a/test/unittest/modular_object_extension_context_capi_test/mock/include/mock_types.h +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/mock_types.h @@ -16,11 +16,29 @@ #ifndef MOCK_TYPES_H #define MOCK_TYPES_H +#include +#include + namespace OHOS { namespace AAFwk { class Want {}; class StartOptions {}; } // namespace AAFwk + +namespace AppExecFwk { +class EventHandler { +public: + bool PostSyncTask(const std::function &task, const char *name) + { + (void)name; + if (!task) { + return false; + } + task(); + return true; + } +}; +} // namespace AppExecFwk } // namespace OHOS #endif // MOCK_TYPES_H diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context.h index 97bfcd5aac..978368bb54 100644 --- a/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context.h +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context.h @@ -17,6 +17,7 @@ #define MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_H #include "ability_runtime_common.h" +#include "ipc_cremote_object.h" struct AbilityBase_Want; typedef struct AbilityBase_Want AbilityBase_Want; @@ -42,6 +43,13 @@ AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_StartSelfUIAbi AbilityRuntime_ErrorCode OH_AbilityRuntime_ModObjExtensionContext_TerminateSelf( OH_AbilityRuntime_ModObjExtensionContextHandle context); +OHIPCRemoteStub* OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, const char *descriptor, + OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData); + +void OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub( + OH_AbilityRuntime_ModObjExtensionContextHandle context, OHIPCRemoteStub *stub); + #ifdef __cplusplus } #endif diff --git a/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context_impl.h b/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context_impl.h index e7afb09e60..b0a7c63027 100644 --- a/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context_impl.h +++ b/test/unittest/modular_object_extension_context_capi_test/mock/include/modular_object_extension_context_impl.h @@ -29,6 +29,12 @@ public: static ErrCode g_startSelfWithOptionsResult; static ErrCode g_terminateResult; + std::shared_ptr GetEventHandler() const + { + static auto handler = std::make_shared(); + return handler; + } + ErrCode StartSelfUIAbility(const AAFwk::Want &want) const { return g_startSelfResult; } ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want, const AAFwk::StartOptions &options) const { return g_startSelfWithOptionsResult; } diff --git a/test/unittest/modular_object_extension_context_capi_test/modular_object_extension_context_capi_test.cpp b/test/unittest/modular_object_extension_context_capi_test/modular_object_extension_context_capi_test.cpp index 6d686834ab..7ee0fc3545 100644 --- a/test/unittest/modular_object_extension_context_capi_test/modular_object_extension_context_capi_test.cpp +++ b/test/unittest/modular_object_extension_context_capi_test/modular_object_extension_context_capi_test.cpp @@ -15,6 +15,8 @@ #include +#include + #include "modular_object_extension_context.h" #include "modular_object_extension_types.h" #include "modular_object_extension_context_impl.h" @@ -37,6 +39,33 @@ ErrCode ModularObjectExtensionContext::g_terminateResult = ERR_OK; int OHOS::AAFwk::CWantManager::g_transformResult = 0; AbilityRuntime_ErrorCode g_checkWantResult = ABILITY_RUNTIME_ERROR_CODE_NO_ERROR; +namespace { +bool g_remoteStubCreateSuccess = true; +int g_remoteStubDestroyCount = 0; +OHIPCRemoteStub *g_lastDestroyedStub = nullptr; +const char *g_lastCreateDescriptor = nullptr; +OH_OnRemoteRequestCallback g_lastRequestCallback = nullptr; +OH_OnRemoteDestroyCallback g_lastDestroyCallback = nullptr; +void *g_lastRemoteStubUserData = nullptr; +OHIPCRemoteStub g_mockRemoteStub {}; +} // namespace + +extern "C" OHIPCRemoteStub* OH_IPCRemoteStub_Create(const char *descriptor, + OH_OnRemoteRequestCallback requestCallback, OH_OnRemoteDestroyCallback destroyCallback, void *userData) +{ + g_lastCreateDescriptor = descriptor; + g_lastRequestCallback = requestCallback; + g_lastDestroyCallback = destroyCallback; + g_lastRemoteStubUserData = userData; + return g_remoteStubCreateSuccess ? &g_mockRemoteStub : nullptr; +} + +extern "C" void OH_IPCRemoteStub_Destroy(OHIPCRemoteStub *stub) +{ + g_lastDestroyedStub = stub; + ++g_remoteStubDestroyCount; +} + AbilityRuntime_ErrorCode CheckWant(AbilityBase_Want *want) { return g_checkWantResult; @@ -53,10 +82,33 @@ public: OHOS::AbilityRuntime::ModularObjectExtensionContext::g_terminateResult = ERR_OK; OHOS::AAFwk::CWantManager::g_transformResult = 0; g_checkWantResult = ABILITY_RUNTIME_ERROR_CODE_NO_ERROR; + g_remoteStubCreateSuccess = true; + g_remoteStubDestroyCount = 0; + g_lastDestroyedStub = nullptr; + g_lastCreateDescriptor = nullptr; + g_lastRequestCallback = nullptr; + g_lastDestroyCallback = nullptr; + g_lastRemoteStubUserData = nullptr; } void TearDown() override {} }; +namespace { +int MockRemoteRequest(uint32_t code, const OHIPCParcel *data, OHIPCParcel *reply, void *userData) +{ + (void)code; + (void)data; + (void)reply; + (void)userData; + return 0; +} + +void MockRemoteDestroy(void *userData) +{ + (void)userData; +} +} // namespace + // ==================== GetBaseContext ==================== HWTEST_F(ModularObjectExtensionContextCapiTest, GetBaseContext_NullContext_001, TestSize.Level1) @@ -326,3 +378,120 @@ HWTEST_F(ModularObjectExtensionContextCapiTest, TerminateSelf_Error_001, TestSiz EXPECT_EQ(ret, ABILITY_RUNTIME_ERROR_CODE_INTERNAL); GTEST_LOG_(INFO) << "TerminateSelf_Error_001 end"; } + +// ==================== CreateIPCRemoteStub ==================== + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_NullDescriptor_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullDescriptor_001 start"; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + nullptr, nullptr, MockRemoteRequest, MockRemoteDestroy, nullptr); + EXPECT_EQ(stub, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullDescriptor_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_NullRequestCallback_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullRequestCallback_001 start"; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + nullptr, "descriptor", nullptr, MockRemoteDestroy, nullptr); + EXPECT_EQ(stub, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_NullRequestCallback_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_WrongType_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_WrongType_001 start"; + auto ctx = std::make_shared(); + ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::SERVICE; + auto cppCtx = std::make_shared(); + ctx->context = cppCtx; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr); + EXPECT_EQ(stub, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_WrongType_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_ExpiredContext_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_ExpiredContext_001 start"; + auto ctx = std::make_shared(); + ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr); + EXPECT_EQ(stub, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_ExpiredContext_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_CreateFail_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_CreateFail_001 start"; + auto ctx = std::make_shared(); + ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT; + auto cppCtx = std::make_shared(); + ctx->context = cppCtx; + g_remoteStubCreateSuccess = false; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, nullptr); + EXPECT_EQ(stub, nullptr); + EXPECT_STREQ(g_lastCreateDescriptor, "descriptor"); + EXPECT_NE(g_lastRequestCallback, nullptr); + EXPECT_NE(g_lastDestroyCallback, nullptr); + EXPECT_NE(g_lastRemoteStubUserData, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_CreateFail_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, CreateIPCRemoteStub_Success_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_Success_001 start"; + int userData = 42; + auto ctx = std::make_shared(); + ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT; + auto cppCtx = std::make_shared(); + ctx->context = cppCtx; + auto stub = OH_AbilityRuntime_ModObjExtensionContext_CreateIPCRemoteStub( + ctx.get(), "descriptor", MockRemoteRequest, MockRemoteDestroy, &userData); + EXPECT_EQ(stub, &g_mockRemoteStub); + EXPECT_STREQ(g_lastCreateDescriptor, "descriptor"); + EXPECT_NE(g_lastRequestCallback, nullptr); + EXPECT_NE(g_lastDestroyCallback, nullptr); + EXPECT_NE(g_lastRemoteStubUserData, nullptr); + GTEST_LOG_(INFO) << "CreateIPCRemoteStub_Success_001 end"; +} + +// ==================== DestroyIPCRemoteStub ==================== + +HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_NullStub_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_NullStub_001 start"; + OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(nullptr, nullptr); + EXPECT_EQ(g_remoteStubDestroyCount, 1); + EXPECT_EQ(g_lastDestroyedStub, nullptr); + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_NullStub_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_Success_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_Success_001 start"; + OHIPCRemoteStub stub {}; + OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(nullptr, &stub); + EXPECT_EQ(g_remoteStubDestroyCount, 1); + EXPECT_EQ(g_lastDestroyedStub, &stub); + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_Success_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextCapiTest, DestroyIPCRemoteStub_ContextAndStubNotNull_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_ContextAndStubNotNull_001 start"; + auto ctx = std::make_shared(); + ctx->type = OHOS::AppExecFwk::ExtensionAbilityType::MODULAR_OBJECT; + auto cppCtx = std::make_shared(); + ctx->context = cppCtx; + OHIPCRemoteStub stub {}; + + OH_AbilityRuntime_ModObjExtensionContext_DestroyIPCRemoteStub(ctx.get(), &stub); + + EXPECT_EQ(g_remoteStubDestroyCount, 1); + EXPECT_EQ(g_lastDestroyedStub, &stub); + GTEST_LOG_(INFO) << "DestroyIPCRemoteStub_ContextAndStubNotNull_001 end"; +} diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/BUILD.gn b/test/unittest/modular_object_extension_context_impl_event_handler_test/BUILD.gn new file mode 100644 index 0000000000..8c32a276ae --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/BUILD.gn @@ -0,0 +1,45 @@ +# Copyright (c) 2026 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/test.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_unittest("modular_object_extension_context_impl_event_handler_test") { + module_out_path = "ability_runtime/ability_runtime/modular_object_extension_context_impl_event_handler_test" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "../../cfi_blocklist.txt" + } + sources = [ + "modular_object_extension_context_impl_event_handler_test.cpp", + "${ability_runtime_path}/frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp", + ] + include_dirs = [ + "mock/include", + ] + external_deps = [ + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + deps = [ ":modular_object_extension_context_impl_event_handler_test" ] +} diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/ability_manager_client.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/ability_manager_client.h new file mode 100644 index 0000000000..84b78cbc51 --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/ability_manager_client.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ABILITY_MANAGER_CLIENT_H +#define MOCK_ABILITY_MANAGER_CLIENT_H + +#endif // MOCK_ABILITY_MANAGER_CLIENT_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/errors.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/errors.h new file mode 100644 index 0000000000..e8e1ec698d --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/errors.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ERRORS_H +#define MOCK_ERRORS_H + +#include +using ErrCode = int32_t; +constexpr ErrCode ERR_OK = 0; + +#endif // MOCK_ERRORS_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/extension_context.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/extension_context.h new file mode 100644 index 0000000000..99c299e09a --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/extension_context.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_EXTENSION_CONTEXT_H +#define MOCK_EXTENSION_CONTEXT_H + +#include +#include "iremote_broker.h" +#include "refbase.h" +#include "iremote_object.h" +#include "errors.h" + +namespace OHOS { +namespace AbilityRuntime { + +class Context : public std::enable_shared_from_this { +public: + Context() = default; + virtual ~Context() = default; +}; + +} // namespace AbilityRuntime + +namespace AppExecFwk { +class EventHandler : public std::enable_shared_from_this { +public: + virtual ~EventHandler() = default; +}; +} // namespace AppExecFwk + +namespace AAFwk { +class Want {}; + +class StartOptions {}; + +class AbilityManagerClient { +public: + static std::shared_ptr GetInstance() + { + static auto instance = std::make_shared(); + return instance; + } + + ErrCode StartSelfUIAbility(const Want &want) + { + return g_startSelfUIAbilityResult; + } + + ErrCode StartSelfUIAbilityWithToken(const Want &want, const sptr &token) + { + return g_startSelfUIAbilityResult; + } + + ErrCode StartSelfUIAbilityWithStartOptions(const Want &want, const StartOptions &options) + { + return g_startSelfUIAbilityWithStartOptionsResult; + } + + ErrCode StartSelfUIAbilityWithStartOptionsAndToken( + const Want &want, const StartOptions &options, const sptr &token) + { + return g_startSelfUIAbilityWithStartOptionsResult; + } + + ErrCode TerminateAbility(const sptr &token, int32_t resultCode, const Want *resultWant) + { + g_terminateCalled = true; + g_lastToken = token.GetRefPtr(); + return g_terminateResult; + } + + static ErrCode g_startSelfUIAbilityResult; + static ErrCode g_startSelfUIAbilityWithStartOptionsResult; + static ErrCode g_terminateResult; + static bool g_terminateCalled; + static IRemoteObject *g_lastToken; + + static void Reset() + { + g_startSelfUIAbilityResult = ERR_OK; + g_startSelfUIAbilityWithStartOptionsResult = ERR_OK; + g_terminateResult = ERR_OK; + g_terminateCalled = false; + g_lastToken = nullptr; + } +}; + +} // namespace AAFwk + +namespace AbilityRuntime { + +class ExtensionContext : public Context { +public: + sptr token_; +}; + +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // MOCK_EXTENSION_CONTEXT_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hilog_tag_wrapper.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hilog_tag_wrapper.h new file mode 100644 index 0000000000..f4178e3fba --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hilog_tag_wrapper.h @@ -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. + */ + +#ifndef OHOS_AAFWK_HILOG_TAG_WRAPPER_H +#define OHOS_AAFWK_HILOG_TAG_WRAPPER_H + +namespace OHOS::AAFwk { +enum class AAFwkLogTag : uint32_t { + DEFAULT = 0xD001300, +}; +} + +using AAFwkTag = OHOS::AAFwk::AAFwkLogTag; + +#define TAG_LOGD(tag, fmt, ...) ((void)0) +#define TAG_LOGI(tag, fmt, ...) ((void)0) +#define TAG_LOGW(tag, fmt, ...) ((void)0) +#define TAG_LOGE(tag, fmt, ...) ((void)0) +#define TAG_LOGF(tag, fmt, ...) ((void)0) + +#endif diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hitrace_meter.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hitrace_meter.h new file mode 100644 index 0000000000..0a3347899b --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/hitrace_meter.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_HITRACE_METER_H +#define MOCK_HITRACE_METER_H + +#define HITRACE_METER_NAME(tag, name) +#define HITRACE_TAG_ABILITY_MANAGER 0 + +#endif // MOCK_HITRACE_METER_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/modular_object_extension_context_impl.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/modular_object_extension_context_impl.h new file mode 100644 index 0000000000..ad0926e0fa --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/modular_object_extension_context_impl.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H +#define MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H + +#include +#include + +#include "extension_context.h" + +namespace OHOS { +namespace AbilityRuntime { + +class ModularObjectExtensionContext : public ExtensionContext { +public: + static const size_t CONTEXT_TYPE_ID; + + // Pure declarations — definitions come from real .cpp (linked via BUILD.gn) + void SetEventHandler(const std::shared_ptr &handler); + + std::shared_ptr GetEventHandler() const; + + // Pure declarations — definitions come from real .cpp (linked via BUILD.gn) + ErrCode StartSelfUIAbility(const AAFwk::Want &want) const; + + ErrCode StartSelfUIAbilityWithStartOptions(const AAFwk::Want &want, + const AAFwk::StartOptions &startOptions) const; + + ErrCode TerminateSelf(); + + bool IsContext(size_t contextTypeId) { return contextTypeId == CONTEXT_TYPE_ID; } + +private: + std::weak_ptr handler_; +}; + +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // MOCK_MODULAR_OBJECT_EXTENSION_CONTEXT_IMPL_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/want.h b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/want.h new file mode 100644 index 0000000000..09040fc870 --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/mock/include/want.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_WANT_H +#define MOCK_WANT_H + +typedef struct AbilityBase_Element { + char *bundleName; + char *moduleName; + char *abilityName; +} AbilityBase_Element; + +typedef struct AbilityBase_Want AbilityBase_Want; +#endif // MOCK_WANT_H diff --git a/test/unittest/modular_object_extension_context_impl_event_handler_test/modular_object_extension_context_impl_event_handler_test.cpp b/test/unittest/modular_object_extension_context_impl_event_handler_test/modular_object_extension_context_impl_event_handler_test.cpp new file mode 100644 index 0000000000..1d4d708060 --- /dev/null +++ b/test/unittest/modular_object_extension_context_impl_event_handler_test/modular_object_extension_context_impl_event_handler_test.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "modular_object_extension_context_impl.h" +#include "extension_context.h" + +using namespace testing::ext; + +namespace OHOS { +class MockRemoteObject : public IRemoteObject { +public: + explicit MockRemoteObject(std::u16string desc) : IRemoteObject(desc) {} + int GetObjectRefCount() override { return 1; } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) override { return true; } + bool RemoveDeathRecipient(const sptr &recipient) override { return true; } + int Dump(int fd, const std::vector &args) override { return 0; } +}; +} // namespace OHOS + +namespace OHOS { +namespace AbilityRuntime { + +class ModularObjectExtensionContextImplEventHandlerTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() override {} + void TearDown() override {} +}; + +class MockEventHandler : public AppExecFwk::EventHandler { +}; + +// ==================== SetEventHandler / GetEventHandler ==================== +// These tests target the REAL implementation in: +// frameworks/native/ability/native/modular_object_extension/modular_object_extension_context_impl.cpp + +HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, GetEventHandler_DefaultNull_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 start"; + auto context = std::make_shared(); + EXPECT_EQ(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_GetSameHandler_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 start"; + auto context = std::make_shared(); + auto handler = std::make_shared(); + context->SetEventHandler(handler); + EXPECT_EQ(context->GetEventHandler(), handler); + GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, GetEventHandler_HandlerExpired_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 start"; + auto context = std::make_shared(); + auto handler = std::make_shared(); + context->SetEventHandler(handler); + handler.reset(); + EXPECT_EQ(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_NullHandler_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SetEventHandler_NullHandler_001 start"; + auto context = std::make_shared(); + context->SetEventHandler(nullptr); + EXPECT_EQ(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "SetEventHandler_NullHandler_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplEventHandlerTest, SetEventHandler_Overwrite_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SetEventHandler_Overwrite_001 start"; + auto context = std::make_shared(); + auto handler1 = std::make_shared(); + auto handler2 = std::make_shared(); + + context->SetEventHandler(handler1); + EXPECT_EQ(context->GetEventHandler(), handler1); + + context->SetEventHandler(handler2); + EXPECT_EQ(context->GetEventHandler(), handler2); + + handler1.reset(); + EXPECT_NE(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "SetEventHandler_Overwrite_001 end"; +} + +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/test/unittest/modular_object_extension_context_impl_test/mock/include/extension_context.h b/test/unittest/modular_object_extension_context_impl_test/mock/include/extension_context.h index 3ec47f0f80..b245e41a4b 100644 --- a/test/unittest/modular_object_extension_context_impl_test/mock/include/extension_context.h +++ b/test/unittest/modular_object_extension_context_impl_test/mock/include/extension_context.h @@ -33,6 +33,13 @@ public: } // namespace AbilityRuntime +namespace AppExecFwk { +class EventHandler : public std::enable_shared_from_this { +public: + virtual ~EventHandler() = default; +}; +} // namespace AppExecFwk + namespace AAFwk { class Want {}; @@ -86,6 +93,13 @@ namespace AbilityRuntime { class ExtensionContext : public Context { public: sptr token_; + +protected: + virtual bool IsContext(size_t contextTypeId) + { + (void)contextTypeId; + return false; + } }; } // namespace AbilityRuntime diff --git a/test/unittest/modular_object_extension_context_impl_test/mock/include/modular_object_extension_context_impl.h b/test/unittest/modular_object_extension_context_impl_test/mock/include/modular_object_extension_context_impl.h index bfed546773..dfa3129491 100644 --- a/test/unittest/modular_object_extension_context_impl_test/mock/include/modular_object_extension_context_impl.h +++ b/test/unittest/modular_object_extension_context_impl_test/mock/include/modular_object_extension_context_impl.h @@ -26,6 +26,16 @@ class ModularObjectExtensionContext : public ExtensionContext { public: static const size_t CONTEXT_TYPE_ID; + void SetEventHandler(const std::shared_ptr &handler) + { + handler_ = handler; + } + + std::shared_ptr GetEventHandler() const + { + return handler_.lock(); + } + ErrCode StartSelfUIAbility(const AAFwk::Want &want) const { return AAFwk::AbilityManagerClient::GetInstance()->StartSelfUIAbility(want); @@ -43,6 +53,9 @@ public: } bool IsContext(size_t contextTypeId) { return contextTypeId == CONTEXT_TYPE_ID; } + +private: + std::weak_ptr handler_; }; } // namespace AbilityRuntime diff --git a/test/unittest/modular_object_extension_context_impl_test/modular_object_extension_context_impl_test.cpp b/test/unittest/modular_object_extension_context_impl_test/modular_object_extension_context_impl_test.cpp index 2ec8727b86..228b980f80 100644 --- a/test/unittest/modular_object_extension_context_impl_test/modular_object_extension_context_impl_test.cpp +++ b/test/unittest/modular_object_extension_context_impl_test/modular_object_extension_context_impl_test.cpp @@ -64,6 +64,40 @@ public: void TearDown() override {} }; +class MockEventHandler : public AppExecFwk::EventHandler { +}; + +// ==================== EventHandler ==================== + +HWTEST_F(ModularObjectExtensionContextImplTest, GetEventHandler_DefaultNull_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 start"; + auto context = std::make_shared(); + EXPECT_EQ(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "GetEventHandler_DefaultNull_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplTest, SetEventHandler_GetSameHandler_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 start"; + auto context = std::make_shared(); + auto handler = std::make_shared(); + context->SetEventHandler(handler); + EXPECT_EQ(context->GetEventHandler(), handler); + GTEST_LOG_(INFO) << "SetEventHandler_GetSameHandler_001 end"; +} + +HWTEST_F(ModularObjectExtensionContextImplTest, GetEventHandler_HandlerExpired_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 start"; + auto context = std::make_shared(); + auto handler = std::make_shared(); + context->SetEventHandler(handler); + handler.reset(); + EXPECT_EQ(context->GetEventHandler(), nullptr); + GTEST_LOG_(INFO) << "GetEventHandler_HandlerExpired_001 end"; +} + // ==================== StartSelfUIAbility ==================== HWTEST_F(ModularObjectExtensionContextImplTest, StartSelfUIAbility_Success_001, TestSize.Level1) diff --git a/test/unittest/modular_object_extension_test/mock/include/ability_handler.h b/test/unittest/modular_object_extension_test/mock/include/ability_handler.h new file mode 100644 index 0000000000..185329a78e --- /dev/null +++ b/test/unittest/modular_object_extension_test/mock/include/ability_handler.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ABILITY_HANDLER_H +#define MOCK_ABILITY_HANDLER_H + +#include + +namespace OHOS { +namespace AppExecFwk { +class EventHandler : public std::enable_shared_from_this { +public: + virtual ~EventHandler() = default; +}; +} // namespace AppExecFwk + +namespace AbilityRuntime { +class AbilityHandler : public AppExecFwk::EventHandler { +public: + ~AbilityHandler() override = default; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // MOCK_ABILITY_HANDLER_H \ No newline at end of file diff --git a/test/unittest/modular_object_extension_test/mock/include/extension.h b/test/unittest/modular_object_extension_test/mock/include/extension.h index 301b95afc0..8cebaba085 100644 --- a/test/unittest/modular_object_extension_test/mock/include/extension.h +++ b/test/unittest/modular_object_extension_test/mock/include/extension.h @@ -18,6 +18,7 @@ #include #include +#include "ability_handler.h" #include "mock_types.h" #include "refbase.h" #include "iremote_object.h" @@ -27,7 +28,6 @@ namespace AbilityRuntime { class AbilityLocalRecord {}; class OHOSApplication {}; -class AbilityHandler {}; struct AbilityInfo { std::string srcEntrance; diff --git a/test/unittest/modular_object_extension_test/mock/include/modular_object_extension_context_impl.h b/test/unittest/modular_object_extension_test/mock/include/modular_object_extension_context_impl.h index ba35759e66..654653ee5b 100644 --- a/test/unittest/modular_object_extension_test/mock/include/modular_object_extension_context_impl.h +++ b/test/unittest/modular_object_extension_test/mock/include/modular_object_extension_context_impl.h @@ -26,6 +26,11 @@ namespace AbilityRuntime { class ModularObjectExtensionContext : public Context { public: ModularObjectExtensionContext() = default; + + void SetEventHandler(const std::shared_ptr &handler) + { + (void)handler; + } }; } // namespace AbilityRuntime