!2713 Set up test env for NARK

Merge pull request !2713 from kurnevichstanislav/setup_nark_tests
This commit is contained in:
openharmony_ci 2024-10-31 09:32:24 +00:00 committed by Gitee
commit 7edae685ce
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 432 additions and 0 deletions

View File

@ -498,6 +498,7 @@ add_subdirectory(lookup_by_name)
add_subdirectory(ets_test_suite)
add_subdirectory(runtime)
add_subdirectory(napi)
add_subdirectory(nark)
if(NOT (PANDA_ENABLE_ADDRESS_SANITIZER OR PANDA_ENABLE_THREAD_SANITIZER))
add_subdirectory(micro-benchmarks)
endif()

View File

@ -0,0 +1,17 @@
# 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(cmake/nark_tests.cmake)
add_subdirectory(nark_gtest)
add_subdirectory(tests)

View File

@ -0,0 +1,69 @@
# 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.
add_custom_target(nark_tests COMMENT "Common target to run NARK ETS tests")
# Add gtest-based tests to nark_tests target.
#
# Example usage:
# nark_add_gtest(test_name
# CPP_SOURCES
# tests/unit1_test.cpp
# tests/unit2_test.cpp
# ETS_SOURCES
# tests/unit1_test.sts
# LIBRARIES
# lib_target1
# lib_target2
# )
function(nark_add_gtest TARGET)
cmake_parse_arguments(
ARG # give prefix `ARG` to each argument
""
""
"CPP_SOURCES;ETS_SOURCES;LIBRARIES"
${ARGN}
)
if(NOT DEFINED ARG_CPP_SOURCES)
message(FATAL_ERROR "CPP_SOURCES is not defined")
endif()
if(DEFINED ARG_ETS_SOURCES)
set(TARGET_GTEST_PACKAGE ${TARGET}_gtest_package)
panda_ets_package_gtest(${TARGET_GTEST_PACKAGE}
ETS_SOURCES ${ARG_ETS_SOURCES}
)
set(NARK_GTEST_ABC_PATH "NARK_GTEST_ABC_PATH=${PANDA_BINARY_ROOT}/abc-gtests/${TARGET_GTEST_PACKAGE}.zip")
endif()
# Add launcher <${TARGET}_gtests> target
set(NATIVE_TESTS_DIR "${PANDA_BINARY_ROOT}/tests/native")
panda_ets_add_gtest(
NAME ${TARGET}
NO_CORES
CUSTOM_PRERUN_ENVIRONMENT
"ARK_ETS_STDLIB_PATH=${PANDA_BINARY_ROOT}/plugins/ets/etsstdlib.abc"
"${NARK_GTEST_ABC_PATH}"
SOURCES ${ARG_CPP_SOURCES}
LIBRARIES ${ARG_LIBRARIES} nark_gtest arkruntime
SANITIZERS ${PANDA_SANITIZERS_LIST}
TSAN_EXTRA_OPTIONS ${ARG_TSAN_EXTRA_OPTIONS}
DEPS_TARGETS etsstdlib ${TARGET_GTEST_PACKAGE}
TEST_RUN_DIR ${NATIVE_TESTS_DIR}
OUTPUT_DIRECTORY ${NATIVE_TESTS_DIR}
)
add_dependencies(nark_tests ${TARGET}_gtests)
endfunction(nark_add_gtest)

View File

@ -0,0 +1,20 @@
# 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.
panda_add_library(nark_gtest INTERFACE)
panda_target_link_libraries(nark_gtest INTERFACE gtest)
panda_target_include_directories(nark_gtest
INTERFACE ${PANDA_ETS_PLUGIN_SOURCE}/tests/nark/nark_gtest/
INTERFACE ${PANDA_ROOT}
)

View File

@ -0,0 +1,200 @@
/**
* 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 PANDA_PLUGINS_ETS_NARK_GTEST_H
#define PANDA_PLUGINS_ETS_NARK_GTEST_H
#include <gtest/gtest.h>
#include <cstdlib>
#include "libpandabase/macros.h"
#include "plugins/ets/runtime/napi/ets_napi.h"
namespace ark::ets::nark::testing {
class NarkTest : public ::testing::Test {
public:
void SetUp() override
{
const char *stdlib = std::getenv("ARK_ETS_STDLIB_PATH");
ASSERT_NE(stdlib, nullptr);
std::vector<EtsVMOption> optionsVector {{EtsOptionType::ETS_BOOT_FILE, stdlib}};
abcPath_ = std::getenv("NARK_GTEST_ABC_PATH");
if (abcPath_.empty()) {
std::cerr << "NARK_GTEST_ABC_PATH must be set" << std::endl;
UNREACHABLE();
}
optionsVector.push_back({EtsOptionType::ETS_BOOT_FILE, abcPath_.c_str()});
EtsVMInitArgs vmArgs;
vmArgs.version = ETS_NAPI_VERSION_1_0;
vmArgs.options = optionsVector.data();
vmArgs.nOptions = static_cast<ets_int>(optionsVector.size());
ASSERT_TRUE(ETS_CreateVM(&vm_, &env_, &vmArgs) == ETS_OK) << "Cannot create ETS VM";
}
void TearDown() override
{
ASSERT_TRUE(vm_->DestroyEtsVM() == ETS_OK) << "Cannot destroy ETS VM";
}
/// Call function with name `fnName` from ETSGLOBAL
template <typename R, typename... Args>
R CallEtsFunction(const std::string &fnName, Args &&...args)
{
std::optional<R> result;
CallEtsFunctionImpl(&result, fnName, std::forward<Args>(args)...);
if constexpr (!std::is_same_v<R, void>) {
return result.value();
}
}
class NativeFunction {
public:
template <typename FuncT>
NativeFunction(const char *functionName, FuncT nativeFunction)
: functionName_(functionName), nativeFunction_(reinterpret_cast<void *>(nativeFunction))
{
}
const char *GetName() const
{
return functionName_;
}
void *GetNativePtr() const
{
return nativeFunction_;
}
private:
const char *functionName_ {nullptr};
void *nativeFunction_ {nullptr};
};
template <typename R, typename... Args>
R CallEtsNativeMethod(const NativeFunction &fn, Args &&...args)
{
std::optional<R> result;
CallEtsNativeMethodImpl(&result, fn, std::forward<Args>(args)...);
if constexpr (!std::is_same_v<R, void>) {
return result.value();
}
}
private:
static std::string GetFindClassFailureMsg(const std::string &className)
{
std::stringstream ss;
ss << "Failed to find class " << className << ".";
return ss.str();
}
static std::string GetFindMethodFailureMsg(const std::string &className, const std::string &methodName)
{
std::stringstream ss;
ss << "Failed to find method `" << methodName << "` in " << className << ".";
return ss.str();
}
template <typename R, typename... Args>
void CallEtsFunctionImpl(std::optional<R> *result, const std::string &fnName, Args &&...args)
{
auto className = "ETSGLOBAL";
ets_class cls = env_->FindClass(className);
ASSERT_NE(cls, nullptr) << GetFindClassFailureMsg(className);
ets_method fn = env_->GetStaticp_method(cls, fnName.data(), nullptr);
ASSERT_NE(fn, nullptr) << GetFindMethodFailureMsg(className, fnName);
*result = DoCallEtsMethod<R>(cls, fn, std::forward<Args>(args)...);
}
template <typename R, typename... Args>
void CallEtsNativeMethodImpl(std::optional<R> *result, const NativeFunction &fn, Args &&...args)
{
auto functionName = fn.GetName();
auto className = "ETSGLOBAL";
auto cls = env_->FindClass(className);
ASSERT_NE(cls, nullptr) << GetFindClassFailureMsg(className);
auto mtd = env_->GetStaticp_method(cls, functionName, nullptr);
ASSERT_NE(mtd, nullptr) << GetFindMethodFailureMsg(className, functionName);
std::array<EtsNativeMethod, 1> method = {{{functionName, nullptr, fn.GetNativePtr()}}};
ASSERT_EQ(env_->RegisterNatives(cls, method.data(), method.size()), ETS_OK)
<< "Failed to register native function " << functionName << ".";
*result = DoCallEtsMethod<R>(cls, mtd, std::forward<Args>(args)...);
ASSERT_EQ(env_->UnregisterNatives(cls), ETS_OK)
<< "Failed to unregister native function " << functionName << ".";
}
template <typename R, typename... Args>
std::optional<R> DoCallEtsMethod(ets_class cls, ets_method mtd, Args &&...args)
{
// NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
if constexpr (std::is_same_v<R, ets_boolean>) {
return env_->CallStaticBooleanMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_byte>) {
return env_->CallStaticByteMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_char>) {
return env_->CallStaticCharMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_short>) {
return env_->CallStaticShortMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_int>) {
return env_->CallStaticIntMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_long>) {
return env_->CallStaticLongMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_float>) {
return env_->CallStaticFloatMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, ets_double>) {
return env_->CallStaticDoubleMethod(cls, mtd, std::forward<Args>(args)...);
} else if constexpr (std::is_same_v<R, void>) {
env_->CallStaticVoidMethod(cls, mtd, args...);
return std::nullopt;
} else if constexpr (std::is_same_v<R, ets_object> || std::is_same_v<R, ets_array>) {
return static_cast<R>(env_->CallStaticObjectMethod(cls, mtd, std::forward<Args>(args)...));
} else {
enum { INCORRECT_TEMPLATE_TYPE = false };
static_assert(INCORRECT_TEMPLATE_TYPE, "Incorrect template type");
}
// NOLINTEND(cppcoreguidelines-pro-type-vararg)
UNREACHABLE();
}
protected:
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
EtsEnv *env_ {nullptr};
private:
std::string abcPath_;
EtsVM *vm_ {nullptr};
};
} // namespace ark::ets::nark::testing
#endif // PANDA_PLUGINS_ETS_NARK_GTEST_H

View File

@ -0,0 +1,21 @@
# 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.
set(EXCLUDED_TEST_PACKAGES)
SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_LIST_DIR} EXCLUDED_TEST_PACKAGES)
foreach(SUBDIR ${SUBDIRS})
get_filename_component(TEST_PACKAGE_NAME ${SUBDIR} NAME)
add_subdirectory(${SUBDIR})
endforeach()

View File

@ -0,0 +1,17 @@
# 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.
nark_add_gtest(nark_test_example
CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/example.cpp
ETS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/example.sts
)

View File

@ -0,0 +1,51 @@
/**
* 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 "nark_gtest.h"
namespace ark::ets::nark::testing {
class ExampleTest : public NarkTest {};
// NOLINTBEGIN(readability-magic-numbers)
TEST_F(ExampleTest, EtsFunctionCall)
{
ets_double p1 = 5.0;
ets_double p2 = 6.0;
auto res = CallEtsFunction<ets_double>("exampleFunction", p1, p2);
ASSERT_EQ(res, p1 + p2);
}
ets_long NativeFuncExample([[maybe_unused]] EtsEnv *env, [[maybe_unused]] ets_class klass, ets_long param1,
ets_long param2)
{
return param1 * param2;
}
TEST_F(ExampleTest, CallNativeFunction)
{
NativeFunction fn("nativeExampleFunction", NativeFuncExample);
ets_long p1 = 12;
ets_long p2 = -123;
// Generic call
auto res = CallEtsNativeMethod<ets_long>(fn, p1, p2);
ASSERT_EQ(res, p1 * p2);
}
// NOLINTEND(readability-magic-numbers)
} // namespace ark::ets::nark::testing

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
class Test {
constructor(a: double, b: double) {
this.a = a;
this.b = b;
}
public Summ(): double {
return this.a + this.b;
}
private a: double;
private b: double;
};
function exampleFunction(a: double, b: double): double {
let t = new Test(a, b);
let res = t.Summ();
return res;
}
native function nativeExampleFunction(a: long, b: long): long;