diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp index d41eaf7d2dea5ba3921bb6c3a4adafed95326345..96c5b4d7793d7e87e0a502ee4eb2cca028d73357 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -47,7 +47,9 @@ #include "module_checker_delegate.h" #include "napi/native_api.h" #include "native_engine/impl/ark/ark_native_engine.h" +#include "native_engine/native_create_env.h" #include "native_engine/native_engine.h" +#include "native_runtime_impl.h" #include "ohos_js_env_logger.h" #include "ohos_js_environment_impl.h" #include "parameters.h" @@ -143,10 +145,51 @@ int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char* messa HILOG_INFO("ArkLog: %{public}s", message); return 0; } + +napi_status CreateNapiEnv(napi_env *env) +{ + HILOG_DEBUG("Called"); + if (env == nullptr) { + HILOG_ERROR("Invalid arg"); + return napi_status::napi_invalid_arg; + } + auto options = JsRuntime::GetChildOptions(); + if (options == nullptr) { + HILOG_ERROR("options is null, it maybe application startup failed!"); + return napi_status::napi_generic_failure; + } + std::shared_ptr jsEnv = nullptr; + auto errCode = NativeRuntimeImpl::GetNativeRuntimeImpl().CreateJsEnv(*options, jsEnv); + if (errCode != napi_status::napi_ok) { + HILOG_ERROR("CreateJsEnv failed"); + return errCode; + } + *env = reinterpret_cast(jsEnv->GetNativeEngine()); + if (env == nullptr) { + HILOG_ERROR("CreateJsEnv failed"); + return napi_status::napi_generic_failure; + } + return NativeRuntimeImpl::GetNativeRuntimeImpl().Init(*options, *env); +} + +napi_status DestroyNapiEnv(napi_env *env) +{ + HILOG_DEBUG("Called"); + if (env == nullptr) { + HILOG_ERROR("Invalid arg"); + return napi_status::napi_invalid_arg; + } + auto errCode = NativeRuntimeImpl::GetNativeRuntimeImpl().RemoveJsEnv(*env); + if (errCode == napi_status::napi_ok) { + *env = nullptr; + } + return errCode; +} + } // namespace std::atomic JsRuntime::hasInstance(false); - +std::shared_ptr JsRuntime::childOptions_ = nullptr; JsRuntime::JsRuntime() { HILOG_DEBUG("JsRuntime costructor."); @@ -163,7 +206,7 @@ std::unique_ptr JsRuntime::Create(const Options& options) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); std::unique_ptr instance; - + SetChildOptions(options); if (!options.preload && options.isStageModel) { auto preloadedInstance = Runtime::GetPreloaded(); #ifdef SUPPORT_GRAPHICS @@ -605,6 +648,8 @@ bool JsRuntime::Initialize(const Options& options) HILOG_ERROR("Create js environment failed."); return false; } + NativeCreateEnv::RegCreateNapiEnvCallback(CreateNapiEnv); + NativeCreateEnv::RegDestroyNapiEnvCallback(DestroyNapiEnv); } else { jsEnv_->StartMonitorJSHeapUsage(); } @@ -658,7 +703,6 @@ bool JsRuntime::Initialize(const Options& options) codePath_ = options.codePath; ReInitJsEnvImpl(options); LoadAotFile(options); - panda::JSNApi::SetBundle(vm, options.isBundle); panda::JSNApi::SetBundleName(vm, options.bundleName); panda::JSNApi::SetHostResolveBufferTracker( @@ -1455,5 +1499,39 @@ std::vector JsRuntime::GetSystemKitsMap(uint32_t version) HILOG_DEBUG("The size of the map is %{public}zu", systemKitsMap.size()); return systemKitsMap; } + +void JsRuntime::SetChildOptions(const Options& options) +{ + if (childOptions_ == nullptr) { + childOptions_ = std::make_shared(); + } + childOptions_->lang = options.lang; + childOptions_->bundleName = options.bundleName; + childOptions_->moduleName = options.moduleName; + childOptions_->codePath = options.codePath; + childOptions_->bundleCodeDir = options.bundleCodeDir; + childOptions_->hapPath = options.hapPath; + childOptions_->arkNativeFilePath = options.arkNativeFilePath; + childOptions_->hapModulePath = options.hapModulePath; + childOptions_->loadAce = options.loadAce; + childOptions_->preload = options.preload; + childOptions_->isBundle = options.isBundle; + childOptions_->isDebugVersion = options.isDebugVersion; + childOptions_->isJsFramework = options.isJsFramework; + childOptions_->isStageModel = options.isStageModel; + childOptions_->isTestFramework = options.isTestFramework; + childOptions_->uid = options.uid; + childOptions_->isUnique = options.isUnique; + childOptions_->moduleCheckerDelegate = options.moduleCheckerDelegate; + childOptions_->apiTargetVersion = options.apiTargetVersion; + childOptions_->packagePathStr = options.packagePathStr; + childOptions_->assetBasePathStr = options.assetBasePathStr; +} + +std::shared_ptr JsRuntime::GetChildOptions() +{ + HILOG_DEBUG("called"); + return childOptions_; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/runtime/native_runtime_impl.cpp b/frameworks/native/runtime/native_runtime_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9acee5100b172634ea003afca81afe34adf6169 --- /dev/null +++ b/frameworks/native/runtime/native_runtime_impl.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "native_runtime_impl.h" + +#include + +#include "bundle_mgr_interface.h" +#include "hilog_wrapper.h" +#include "iservice_registry.h" +#include "js_environment.h" +#include "js_module_reader.h" +#include "js_worker.h" +#include "ohos_js_env_logger.h" +#include "ohos_js_environment_impl.h" +#include "parameters.h" +#include "system_ability_definition.h" + +using Extractor = OHOS::AbilityBase::Extractor; +using ExtractorUtil = OHOS::AbilityBase::ExtractorUtil; + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr int64_t DEFAULT_GC_POOL_SIZE = 0x10000000; // 256MB +constexpr size_t MAX_ENV_COUNT = 16; +const std::string SANDBOX_ARK_PROIFILE_PATH = "/data/storage/ark-profile"; +int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char* message) +{ + HILOG_INFO("ArkLog: %{public}s", message); + return 0; +} +} +NativeRuntimeImpl::NativeRuntimeImpl() +{} + +NativeRuntimeImpl::~NativeRuntimeImpl() +{ + std::lock_guard lock(envMutex_); + for (auto it : envMap_) { + it.second.reset(); + it.second = nullptr; + } + envMap_.clear(); + threadIds_.clear(); +} + +NativeRuntimeImpl& NativeRuntimeImpl::GetNativeRuntimeImpl() +{ + static NativeRuntimeImpl nativeRuntimeImpl; + return nativeRuntimeImpl; +} + +napi_status NativeRuntimeImpl::CreateJsEnv(const Options& options, std::shared_ptr& jsEnv) +{ + HILOG_DEBUG("called"); + panda::RuntimeOption pandaOption; + int arkProperties = OHOS::system::GetIntParameter("persist.ark.properties", -1); + std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", ""); + size_t gcThreadNum = OHOS::system::GetUintParameter("persist.ark.gcthreads", 7); + size_t longPauseTime = OHOS::system::GetUintParameter("persist.ark.longpausetime", 40); + pandaOption.SetArkProperties(arkProperties); + pandaOption.SetArkBundleName(bundleName); + pandaOption.SetGcThreadNum(gcThreadNum); + pandaOption.SetLongPauseTime(longPauseTime); + HILOG_INFO("NativeRuntimeImpl::Initialize ark properties = %{public}d bundlename = %{public}s", + arkProperties, bundleName.c_str()); + pandaOption.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC); + pandaOption.SetGcPoolSize(DEFAULT_GC_POOL_SIZE); + pandaOption.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::FOLLOW); + pandaOption.SetLogBufPrint(PrintVmLog); + + bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true); + std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", ""); + pandaOption.SetEnableAsmInterpreter(asmInterpreterEnabled); + pandaOption.SetAsmOpcodeDisableRange(asmOpcodeDisableRange); + + bool useAbilityRuntime = (options.isStageModel) || (options.isTestFramework); + if (useAbilityRuntime) { + bool aotEnabled = OHOS::system::GetBoolParameter("persist.ark.aot", true); + pandaOption.SetEnableAOT(aotEnabled); + pandaOption.SetProfileDir(SANDBOX_ARK_PROIFILE_PATH); + } + + OHOSJsEnvLogger::RegisterJsEnvLogger(); + // options eventRunner is nullptr + jsEnv = std::make_shared(std::make_unique(options.eventRunner)); + if (jsEnv == nullptr || !jsEnv->Initialize(pandaOption, static_cast(this)) + || jsEnv->GetNativeEngine() == nullptr) { + HILOG_ERROR("Initialize js environment failed."); + return napi_status::napi_ok; + } + jsEnv->GetNativeEngine()->MarkNativeThread(); + return AddEnv(reinterpret_cast(jsEnv->GetNativeEngine()), jsEnv); +} + +napi_status NativeRuntimeImpl::Init(const Options& options, napi_env env) +{ + auto jsEnv = GetJsEnv(env); + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return napi_status::napi_generic_failure; + } + + auto vm = GetEcmaVm(jsEnv); + if (!vm) { + HILOG_ERROR("vm is nullptr."); + return napi_status::napi_generic_failure; + } + + bool isModular = false; + if (!options.preload) { + LoadAotFile(options, jsEnv); + panda::JSNApi::SetBundle(vm, options.isBundle); + panda::JSNApi::SetBundleName(vm, options.bundleName); + panda::JSNApi::SetHostResolveBufferTracker( + vm, JsModuleReader(options.bundleName, options.hapPath, options.isUnique)); + isModular = !panda::JSNApi::IsBundle(vm); + panda::JSNApi::SetSearchHapPathTracker( + vm, [options](const std::string moduleName, std::string &hapPath) -> bool { + if (options.hapModulePath.find(moduleName) == options.hapModulePath.end()) { + return false; + } + hapPath = options.hapModulePath.find(moduleName)->second; + return true; + }); + } + + if (!preloaded_) { + InitConsoleModule(jsEnv); + } + + if (!options.preload) { + auto operatorObj = std::make_shared(options.bundleName, isModular); + InitSourceMap(operatorObj, jsEnv); + if (!options.isUnique) { + InitTimerModule(jsEnv); + } + InitWorkerModule(options, jsEnv); + SetModuleLoadChecker(options.moduleCheckerDelegate, jsEnv); + SetRequestAotCallback(jsEnv); + + if (!InitLoop(jsEnv)) { + HILOG_ERROR("Initialize loop failed."); + return napi_status::napi_generic_failure; + } + } + + preloaded_ = options.preload; + return napi_status::napi_ok; +} + +napi_status NativeRuntimeImpl::AddEnv(napi_env env, std::shared_ptr jsEnv) +{ + std::lock_guard lock(envMutex_); + pid_t threadId = gettid(); + if (threadIds_.find(threadId) != threadIds_.end()) { + HILOG_ERROR("already created!"); + return napi_status::napi_create_ark_runtime_only_one_env_per_thread; + } + if (envMap_.size() >= MAX_ENV_COUNT) { + HILOG_ERROR("the maximum number of runtime environments that can be created is 16!"); + return napi_status::napi_create_ark_runtime_too_many_envs; + } + threadIds_.insert(threadId); + HILOG_DEBUG("add threadId %{public}zu", threadId); + auto it = envMap_.find(env); + if (it == envMap_.end()) { + envMap_[env] = jsEnv; + return napi_status::napi_ok; + } + return napi_status::napi_generic_failure; +} + +napi_status NativeRuntimeImpl::RemoveJsEnv(napi_env env) +{ + std::lock_guard lock(envMutex_); + pid_t threadId = gettid(); + HILOG_DEBUG("remove threadId %{public}zu", threadId); + threadIds_.erase(threadId); + auto it = envMap_.find(env); + if (it != envMap_.end()) { + it->second.reset(); + it->second = nullptr; + envMap_.erase(env); + return napi_status::napi_ok; + } + return napi_status::napi_destroy_ark_runtime_env_not_exist; +} + +panda::ecmascript::EcmaVM* NativeRuntimeImpl::GetEcmaVm(const std::shared_ptr& jsEnv) const +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return nullptr; + } + return jsEnv->GetVM(); +} + +std::shared_ptr NativeRuntimeImpl::GetJsEnv(napi_env env) +{ + std::lock_guard lock(envMutex_); + auto jsEnv = envMap_.find(env); + if (jsEnv != envMap_.end()) { + return jsEnv->second; + } + return nullptr; +} + +void NativeRuntimeImpl::LoadAotFile(const Options& options, const std::shared_ptr& jsEnv) +{ + auto vm = GetEcmaVm(jsEnv); + if (!vm || options.hapPath.empty()) { + return; + } + + bool newCreate = false; + std::string loadPath = ExtractorUtil::GetLoadFilePath(options.hapPath); + std::shared_ptr extractor = ExtractorUtil::GetExtractor(loadPath, newCreate, true); + if (extractor != nullptr && newCreate) { + panda::JSNApi::LoadAotFile(vm, options.moduleName); + } +} + +void NativeRuntimeImpl::InitConsoleModule(const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + jsEnv->InitConsoleModule(); +} + +void NativeRuntimeImpl::InitSourceMap(const std::shared_ptr operatorObj, + const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + jsEnv->InitSourceMap(operatorObj); +} + +void NativeRuntimeImpl::InitTimerModule(const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + jsEnv->InitTimerModule(); +} + +void NativeRuntimeImpl::SetModuleLoadChecker(const std::shared_ptr& moduleCheckerDelegate, + const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + jsEnv->SetModuleLoadChecker(moduleCheckerDelegate); +} + +void NativeRuntimeImpl::SetRequestAotCallback(const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + auto callback = [](const std::string& bundleName, const std::string& moduleName, int32_t triggerMode) -> int32_t { + auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + HILOG_ERROR("Failed to get system ability manager."); + return ERR_INVALID_VALUE; + } + + auto remoteObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObj == nullptr) { + HILOG_ERROR("Remote object is nullptr."); + return ERR_INVALID_VALUE; + } + + auto bundleMgr = iface_cast(remoteObj); + if (bundleMgr == nullptr) { + HILOG_ERROR("Failed to get bundle manager."); + return ERR_INVALID_VALUE; + } + + HILOG_DEBUG("Reset compile status, bundleName: %{public}s, moduleName: %{public}s, triggerMode: %{public}d.", + bundleName.c_str(), moduleName.c_str(), triggerMode); + return bundleMgr->ResetAOTCompileStatus(bundleName, moduleName, triggerMode); + }; + + jsEnv->SetRequestAotCallback(callback); +} + +bool NativeRuntimeImpl::InitLoop(const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return false; + } + return jsEnv->InitLoop(); +} + +void NativeRuntimeImpl::InitWorkerModule(const Options& options, const std::shared_ptr& jsEnv) +{ + if (jsEnv == nullptr) { + HILOG_ERROR("jsEnv is nullptr."); + return; + } + + std::shared_ptr workerInfo = std::make_shared(); + workerInfo->codePath = options.codePath; + workerInfo->isDebugVersion = options.isDebugVersion; + workerInfo->isBundle = options.isBundle; + workerInfo->packagePathStr = options.packagePathStr; + workerInfo->assetBasePathStr = options.assetBasePathStr; + workerInfo->hapPath = options.hapPath; + workerInfo->isStageModel = options.isStageModel; + workerInfo->moduleName = options.moduleName; + if (options.isJsFramework) { + SetJsFramework(); + } + jsEnv->InitWorkerModule(workerInfo); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn index 30073696b11f975ec68edb765b92fd26e1365ad6..726682be36ee2a4a4933e06f7105b563500389b5 100644 --- a/interfaces/inner_api/runtime/BUILD.gn +++ b/interfaces/inner_api/runtime/BUILD.gn @@ -67,6 +67,7 @@ ohos_shared_library("runtime") { "${ability_runtime_native_path}/runtime/js_runtime.cpp", "${ability_runtime_native_path}/runtime/js_runtime_utils.cpp", "${ability_runtime_native_path}/runtime/js_worker.cpp", + "${ability_runtime_native_path}/runtime/native_runtime_impl.cpp", "${ability_runtime_native_path}/runtime/ohos_js_env_logger.cpp", "${ability_runtime_native_path}/runtime/ohos_js_environment_impl.cpp", "${ability_runtime_native_path}/runtime/ohos_loop_handler.cpp", diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h index e9ee36665fd0b34d925c288f10875725a7132b02..5c51bc97eed8336884a0dc18dfebe5852aba5412 100644 --- a/interfaces/inner_api/runtime/include/js_runtime.h +++ b/interfaces/inner_api/runtime/include/js_runtime.h @@ -65,6 +65,7 @@ public: static bool ReadSourceMapData(const std::string& hapPath, const std::string& sourceMapPath, std::string& content); + static std::shared_ptr GetChildOptions(); JsRuntime(); ~JsRuntime() override; @@ -135,6 +136,7 @@ private: bool Initialize(const Options& options); void Deinitialize(); + static void SetChildOptions(const Options& options); int32_t JsperfProfilerCommandParse(const std::string &command, int32_t defaultValue); @@ -154,6 +156,8 @@ private: static std::atomic hasInstance; + static std::shared_ptr childOptions_; + private: bool CreateJsEnv(const Options& options); void PreloadAce(const Options& options); diff --git a/interfaces/inner_api/runtime/include/native_runtime_impl.h b/interfaces/inner_api/runtime/include/native_runtime_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..c1ecb6703ffaf53726c724581c8f88caa1083c82 --- /dev/null +++ b/interfaces/inner_api/runtime/include/native_runtime_impl.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_ABILITY_RUNTIME_NATIVE_RUNTIME_IMPL_H +#define ABILITY_ABILITY_RUNTIME_NATIVE_RUNTIME_IMPL_H + +#include +#include +#include +#include + +#include "js_environment.h" +#include "native_engine/native_engine.h" +#include "runtime.h" + +using Options = OHOS::AbilityRuntime::Runtime::Options; +namespace OHOS { +namespace AbilityRuntime { +class NativeRuntimeImpl { +public: + NativeRuntimeImpl(const NativeRuntimeImpl&) = delete; + NativeRuntimeImpl& operator=(const NativeRuntimeImpl&) = delete; + static NativeRuntimeImpl& GetNativeRuntimeImpl(); + napi_status CreateJsEnv(const Options& options, std::shared_ptr& jsEnv); + napi_status RemoveJsEnv(napi_env env); + napi_status Init(const Options& options, napi_env env); + +private: + NativeRuntimeImpl(); + ~NativeRuntimeImpl(); + napi_status AddEnv(napi_env env, std::shared_ptr jsEnv); + panda::ecmascript::EcmaVM* GetEcmaVm(const std::shared_ptr& jsEnv) const; + std::shared_ptr GetJsEnv(napi_env env); + void LoadAotFile(const Options& options, const std::shared_ptr& jsEnv); + void InitConsoleModule(const std::shared_ptr& jsEnv); + void InitSourceMap(const std::shared_ptr operatorObj, + const std::shared_ptr& jsEnv); + void InitTimerModule(const std::shared_ptr& jsEnv); + void SetModuleLoadChecker(const std::shared_ptr& moduleCheckerDelegate, + const std::shared_ptr& jsEnv); + void SetRequestAotCallback(const std::shared_ptr& jsEnv); + bool InitLoop(const std::shared_ptr& jsEnv); + void InitWorkerModule(const Options& options, const std::shared_ptr& jsEnv); + std::unordered_map> envMap_; + std::unordered_set threadIds_; + bool preloaded_ = false; + std::mutex envMutex_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // ABILITY_ABILITY_RUNTIME_NATIVE_RUNTIME_IMPL_H \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index fc7b430dea0e860406879672fb1587ea70343a28..2859d08d6290fdecf327d118478f298cbf57e13a 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -445,6 +445,7 @@ group("unittest") { "mission_listener_stub_test:unittest", "mission_listener_test:unittest", "napi_base_context_test:unittest", + "native_runtime_test:unittest", "os_account_manager_wrapper_test:unittest", "page_state_data_test:unittest", "pending_want_key_test:unittest", diff --git a/test/unittest/native_runtime_test/BUILD.gn b/test/unittest/native_runtime_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c6bf4918b12d7721cd2ed0d7f56f5995360259fe --- /dev/null +++ b/test/unittest/native_runtime_test/BUILD.gn @@ -0,0 +1,49 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/test.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +module_output_path = "ability_runtime/native_runtime" + +ohos_unittest("native_runtime_test") { + module_out_path = module_output_path + include_dirs = [ "${ability_runtime_innerkits_path}/runtime/include" ] + + sources = [ "native_runtime_test.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_base:extractortool", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "ets_runtime:libark_jsruntime", + "hilog:libhilog", + "init:libbegetutil", + "ipc:ipc_core", + "napi:ace_napi", + "samgr:samgr_proxy", + ] +} + +group("unittest") { + testonly = true + deps = [ ":native_runtime_test" ] +} diff --git a/test/unittest/native_runtime_test/native_runtime_test.cpp b/test/unittest/native_runtime_test/native_runtime_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bebf6b5463a542b966b7ef65559f46a5acb14268 --- /dev/null +++ b/test/unittest/native_runtime_test/native_runtime_test.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hilog_wrapper.h" +#include "js_runtime.h" +#include "js_environment.h" +#include "native_runtime_impl.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace AbilityRuntime { + +class NativeRuntimeImplTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void NativeRuntimeImplTest::SetUpTestCase() {} + +void NativeRuntimeImplTest::TearDownTestCase() {} + +void NativeRuntimeImplTest::SetUp() {} + +void NativeRuntimeImplTest::TearDown() {} + +/** + * @tc.name: NativeRuntimeImplTest_001 + * @tc.desc: basic function test. + * @tc.type: FUNC + */ +HWTEST_F(NativeRuntimeImplTest, NativeRuntimeImplTest_001, TestSize.Level1) +{ + HILOG_INFO("NativeRuntimeImplTest_001 start"); + Options options; + std::shared_ptr jsEnv = nullptr; + auto err = NativeRuntimeImpl::GetNativeRuntimeImpl().CreateJsEnv(options, jsEnv); + EXPECT_EQ(err, napi_status::napi_ok); + + err = NativeRuntimeImpl::GetNativeRuntimeImpl().RemoveJsEnv(reinterpret_cast(jsEnv->GetNativeEngine())); + EXPECT_EQ(err, napi_status::napi_ok); + HILOG_INFO("NativeRuntimeImplTest_001 end"); +} + +/** + * @tc.name: NativeRuntimeImplTest_002 + * @tc.desc: basic function test. + * @tc.type: FUNC + */ +HWTEST_F(NativeRuntimeImplTest, NativeRuntimeImplTest_002, TestSize.Level1) +{ + HILOG_INFO("NativeRuntimeImplTest_002 start"); + Options options; + std::shared_ptr jsEnv = nullptr; + auto err = NativeRuntimeImpl::GetNativeRuntimeImpl().CreateJsEnv(options, jsEnv); + EXPECT_EQ(err, napi_status::napi_ok); + + std::shared_ptr jsEnv2 = nullptr; + err = NativeRuntimeImpl::GetNativeRuntimeImpl().CreateJsEnv(options, jsEnv2); + EXPECT_EQ(err, napi_status::napi_create_ark_runtime_only_one_env_per_thread); + + err = NativeRuntimeImpl::GetNativeRuntimeImpl().RemoveJsEnv(reinterpret_cast(jsEnv->GetNativeEngine())); + EXPECT_EQ(err, napi_status::napi_ok); + + err = NativeRuntimeImpl::GetNativeRuntimeImpl().RemoveJsEnv(reinterpret_cast(jsEnv2->GetNativeEngine())); + EXPECT_EQ(err, napi_status::napi_destroy_ark_runtime_env_not_exist); + HILOG_INFO("NativeRuntimeImplTest_002 end"); +} + +/** + * @tc.name: NativeRuntimeImplTest_003 + * @tc.desc: basic function test. + * @tc.type: FUNC + */ +HWTEST_F(NativeRuntimeImplTest, NativeRuntimeImplTest_003, TestSize.Level1) +{ + HILOG_INFO("NativeRuntimeImplTest_003 start"); + Options options; + std::shared_ptr jsEnv = nullptr; + auto err = NativeRuntimeImpl::GetNativeRuntimeImpl().CreateJsEnv(options, jsEnv); + EXPECT_EQ(err, napi_status::napi_ok); + + napi_env env = reinterpret_cast(jsEnv->GetNativeEngine()); + err = NativeRuntimeImpl::GetNativeRuntimeImpl().Init(options, env); + EXPECT_EQ(err, napi_status::napi_ok); + + err = NativeRuntimeImpl::GetNativeRuntimeImpl().RemoveJsEnv(env); + EXPECT_EQ(err, napi_status::napi_ok); + HILOG_INFO("NativeRuntimeImplTest_003 end"); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file