diff --git a/CMakeLists.txt b/CMakeLists.txt index aa6bc81e1180a918c0e10f57e29752671016ee8b..071f23558e80d00cc0a32010937092ce81513ac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,4 +39,7 @@ if(ENABLE_TORCH_FRONT) endif() add_subdirectory(${PROJECT_SOURCE_DIR}/inferrt/src) -add_subdirectory(${PROJECT_SOURCE_DIR}/tests) \ No newline at end of file +if(BUILD_TESTS) + enable_testing() + add_subdirectory(${PROJECT_SOURCE_DIR}/tests) +endif() \ No newline at end of file diff --git a/build.sh b/build.sh index 8cb2c3d7e4ddd464e89dea460dc4d7a84477439d..4cded9f004302d97abbb14a512ebab85bb46465a 100755 --- a/build.sh +++ b/build.sh @@ -19,6 +19,7 @@ usage() echo " -t Build and run tests, default off" echo " -f Enable frontend, default compile all frontend" echo " -b Enable backend, default compile cpu backend" + echo " -e Enable download cmake compile dependency from gitee, default off" } process_options() @@ -30,7 +31,7 @@ process_options() export ENABLE_MINDSPORE_FRONT=1 export ENABLE_TORCH_FRONT=1 - while getopts 'Dd:hitf:b:' OPT; do + while getopts 'Dd:hitf:b:e' OPT; do case $OPT in D) # Debug version or not. @@ -75,6 +76,7 @@ process_options() exit 1 fi ;; + e) export ENABLE_GITEE=1;; ?) usage exit 1 @@ -98,6 +100,8 @@ if [[ $ENABLE_CPU == 1 ]]; then INFERRT_CMAKE_ARGS="${INFERRT_CMAKE_ARGS} -DENABLE_CPU=on" fi +if [[ $ENABLE_GITEE == 1 ]]; then + INFERRT_CMAKE_ARGS="${INFERRT_CMAKE_ARGS} -DENABLE_GITEE=on" if [[ $ENABLE_TORCH_FRONT == 1 ]]; then INFERRT_CMAKE_ARGS="${INFERRT_CMAKE_ARGS} -DENABLE_TORCH_FRONT=on" fi @@ -162,21 +166,6 @@ echo "# 2/2: ./da sample/da_llm_sample.da" $BUILD_DIR/inferrt/src/da $INFERRT_PATH/inferrt/src/lang/sample/da_llm_sample.da echo "==============================" -# Run hardware test -if [[ $BUILD_TESTS == 1 ]]; then - echo "==============================" - echo "Run test case:" - if [[ $ENABLE_ASCEND == 1 ]]; then - echo "Ascend backend test case" - ./tests/hardware_ascend_test_obj - else - echo "CPU backend test case" - ./tests/hardware_cpu_test_obj - fi - echo "Tests completed." - echo "==============================" -fi - cd $CURRENT_PATH # 1. Clean up previous build artifacts diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..2b2a06efbf77cb7a1f97da92ab277cab2b3ddc3b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +torch==2.5.1 +torch-npu==2.5.1 +typing_extensions==4.15.0 +wheel==0.45.1 \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1fe631425cd4ba2edb42c4ad700a287248e605d2..4ee08ed5d0b4c14f4611f82f5ff45a8b8480d1dd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,38 +1 @@ -check_debug_log_out() - -if(ENABLE_ASCEND AND BUILD_TESTS) - message(STATUS "Backend Ascend enabled") - if(DEFINED ENV{ASCEND_CUSTOM_PATH}) - set(ASCEND_PATH $ENV{ASCEND_CUSTOM_PATH}) - else() - set(ASCEND_PATH /usr/local/Ascend) - endif() - - message("Note compile ascend path: ${ASCEND_PATH}") - include_directories(${ASCEND_PATH}/latest/include/) - link_directories(${ASCEND_PATH}/latest/lib64/) - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ldl") - - include_directories(${PROJECT_SOURCE_DIR}/inferrt/src) - - add_executable(hardware_ascend_test_obj ./hardware/hardware_test.cc) - target_link_libraries(hardware_ascend_test_obj hardware_ascend_obj) - - enable_testing() - add_test(NAME hardware_ascend_test COMMAND hardware_ascend_test_obj) -else() - message("Note ascend backend is disabled") -endif() - - -if(ENABLE_CPU) - message(STATUS "Backend CPU enabled") - include_directories(${PROJECT_SOURCE_DIR}/inferrt/src) - add_executable(hardware_cpu_test_obj ./hardware/hardware_cpu_test.cc) - target_link_libraries(hardware_cpu_test_obj hardware_cpu_obj) - enable_testing() - add_test(NAME hardware_cpu_test COMMAND hardware_cpu_test_obj) -else() - message("Note cpu backend is disabled") -endif() \ No newline at end of file +add_subdirectory(ut) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/test_ms_mul.py b/tests/check_ms_mul.py similarity index 100% rename from tests/test_ms_mul.py rename to tests/check_ms_mul.py diff --git a/tests/mark_utils.py b/tests/mark_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..41cab566baacafb2b6f5c7872a0edde628b35980 --- /dev/null +++ b/tests/mark_utils.py @@ -0,0 +1,43 @@ +# Copyright 2024 Huawei Technologies 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. +# ============================================================================ + +""" define marks """ +import pytest + + +def arg_mark(plat_marks, level_mark, card_mark, essential_mark): + optional_plat_marks = ['platform_ascend', 'platform_ascend910b', 'platform_ascend310p', 'platform_gpu', + 'cpu_linux', 'cpu_windows', 'cpu_macos'] + optional_level_marks = ['level0', 'level1', 'level2', 'level3', 'level4'] + optional_card_marks = ['onecard', 'allcards', 'dryrun', 'dryrun_only'] + optional_essential_marks = ['essential', 'unessential'] + if not plat_marks or not set(plat_marks).issubset(set(optional_plat_marks)): + raise ValueError(f"wrong plat_marks values {plat_marks}") + if level_mark not in optional_level_marks: + raise ValueError("wrong level_mark value") + if card_mark not in optional_card_marks: + raise ValueError("wrong card_mark value") + if essential_mark not in optional_essential_marks: + raise ValueError("wrong essential_mark value") + + def decorator(func): + for plat_mark in plat_marks: + func = getattr(pytest.mark, plat_mark)(func) + func = getattr(pytest.mark, level_mark)(func) + func = getattr(pytest.mark, card_mark)(func) + func = getattr(pytest.mark, essential_mark)(func) + return func + + return decorator diff --git a/tests/st/__init__.py b/tests/st/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/st/check/__init__.py b/tests/st/check/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/st/check/check_api.py b/tests/st/check/test_check_api.py similarity index 54% rename from tests/st/check/check_api.py rename to tests/st/check/test_check_api.py index 62af17003347fb71d2e0f5e09d37190deaacd3d8..07beedf8554320845aa1825180c37dd18a9161b5 100644 --- a/tests/st/check/check_api.py +++ b/tests/st/check/test_check_api.py @@ -12,21 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import pytest from mrt import jit -import argparse +from tests.mark_utils import arg_mark -_arg_parser = argparse.ArgumentParser() -_arg_parser.add_argument('--dump', '-d', type=bool, default=False, required=False, help="if dump compiler information") -_args = _arg_parser.parse_args() +@arg_mark(plat_marks=["cpu_linux"], level_mark="level0", card_mark="onecard", essential_mark="essential") +@pytest.mark.parametrize("dump", (True, False)) +def test_jit(dump): + @jit(dump_compiler=dump) + def run_check(x, y): + print('hello world.\n') + z = x * y + z = z + x - y + z = z / y + return z -@jit(dump_compiler=_args.dump) -def run_check(x, y): - print('hello world.\n') - z = x * y - z = z + x - y - z = z / y - return z - -assert run_check(12, 6) == 13 -print("The result is correct. 'mrt' module has been installed successfully.") \ No newline at end of file + assert run_check(12, 6) == 13 + print("The result is correct. 'mrt' module has been installed successfully.") \ No newline at end of file diff --git a/tests/st/check/test_check_api2.py b/tests/st/check/test_check_api2.py new file mode 100644 index 0000000000000000000000000000000000000000..3204f00c0155bf7a84ac8410b918b5a53a651a7a --- /dev/null +++ b/tests/st/check/test_check_api2.py @@ -0,0 +1,32 @@ +# Copyright 2025 Huawei Technologies 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 pytest +from mrt import jit +from tests.mark_utils import arg_mark + + +@arg_mark(plat_marks=["cpu_linux"], level_mark="level0", card_mark="onecard", essential_mark="essential") +@pytest.mark.parametrize("dump", (True, False)) +def test_jit(dump): + @jit(dump_compiler=dump) + def run_check(x, y): + print('hello world.\n') + z = x / y + z = z + x - y + z = z * y + return z + + assert run_check(12, 6) == 48 + print("The result is correct. 'mrt' module has been installed successfully.") \ No newline at end of file diff --git a/tests/st/common/__init__.py b/tests/st/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/st/common/random_generator.py b/tests/st/common/random_generator.py new file mode 100644 index 0000000000000000000000000000000000000000..283a5403930e19880eb892cd4c0ea235dcfdd54c --- /dev/null +++ b/tests/st/common/random_generator.py @@ -0,0 +1,23 @@ +import numpy as np + + +def get_numpy_global_seed(): + return 1967515154 + + +def set_numpy_global_seed(): + np.random.seed(get_numpy_global_seed()) + + +def get_numpy_random_seed(): + ii32 = np.iinfo(np.int32) + seed = np.random.randint(0, ii32.max, size=1).astype(np.int32) + return seed + + +def set_numpy_random_seed(seed=None): + if seed is None: + set_numpy_global_seed() + else: + print(f"random_generator: set random seed={seed} for numpy.random.method.") + np.random.seed(seed) diff --git a/tests/ut/CMakeLists.txt b/tests/ut/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..da8ed956f6bd903fff3b88b8b4512c54a607d063 --- /dev/null +++ b/tests/ut/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(cpp) \ No newline at end of file diff --git a/tests/ut/cpp/CMakeLists.txt b/tests/ut/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..0ecee91457419aeae450294498a2952a33f218a2 --- /dev/null +++ b/tests/ut/cpp/CMakeLists.txt @@ -0,0 +1,62 @@ +check_debug_log_out() + +include(FetchContent) +if(ENABLE_GITEE) + set(PKG_GIT_REPO https://github.com/google/googletest.git) +else() + set(PKG_GIT_REPO https://gitee.com/mirrors/googletest.git) +endif() +FetchContent_Declare( + googletest + GIT_REPOSITORY ${PKG_GIT_REPO} + GIT_TAG release-1.12.1 +) +FetchContent_MakeAvailable(googletest) + +message(STATUS "Build UT testcases") +include_directories(${PROJECT_SOURCE_DIR}/inferrt/src) +file(GLOB_RECURSE IR_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + "../../../inferrt/src/ir/tensor/*.cc" + ) +add_library(ut_ir_static STATIC ${IR_SRC_LIST}) + +add_executable(ut_storage_test_obj ./ir/storage_test.cc) +target_link_libraries(ut_storage_test_obj + PRIVATE + ut_ir_static + GTest::gtest_main +) +add_test(NAME ut_storage_test COMMAND ut_storage_test_obj) + + +if(ENABLE_ASCEND) + message(STATUS "Backend Ascend enabled") + if(DEFINED ENV{ASCEND_CUSTOM_PATH}) + set(ASCEND_PATH $ENV{ASCEND_CUSTOM_PATH}) + else() + set(ASCEND_PATH /usr/local/Ascend) + endif() + + message("Note compile ascend path: ${ASCEND_PATH}") + include_directories(${ASCEND_PATH}/latest/include/) + link_directories(${ASCEND_PATH}/latest/lib64/) + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ldl") + + add_executable(hardware_ascend_test_obj ./hardware/hardware_test.cc) + target_link_libraries(hardware_ascend_test_obj hardware_ascend_obj) + + add_test(NAME hardware_ascend_test COMMAND hardware_ascend_test_obj) +else() + message("Note ascend backend is disabled") +endif() + + +if(ENABLE_CPU) + message(STATUS "Backend CPU enabled") + add_executable(hardware_cpu_test_obj ./hardware/hardware_cpu_test.cc) + target_link_libraries(hardware_cpu_test_obj hardware_cpu_obj) + add_test(NAME hardware_cpu_test COMMAND hardware_cpu_test_obj) +else() + message("Note cpu backend is disabled") +endif() diff --git a/tests/hardware/hardware_cpu_test.cc b/tests/ut/cpp/hardware/hardware_cpu_test.cc similarity index 100% rename from tests/hardware/hardware_cpu_test.cc rename to tests/ut/cpp/hardware/hardware_cpu_test.cc diff --git a/tests/hardware/hardware_test.cc b/tests/ut/cpp/hardware/hardware_test.cc similarity index 100% rename from tests/hardware/hardware_test.cc rename to tests/ut/cpp/hardware/hardware_test.cc diff --git a/tests/ut/cpp/ir/storage_test.cc b/tests/ut/cpp/ir/storage_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..a0e0936feccd43eb7752538028426a8d3704414e --- /dev/null +++ b/tests/ut/cpp/ir/storage_test.cc @@ -0,0 +1,119 @@ +/** + * Copyright 2025 Huawei Technologies 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 "gtest/gtest.h" +#include "ir/tensor/storage.h" +#include "common/common.h" + +namespace mrt { +namespace ir { + +class StorageTest : public testing::Test { +protected: + void SetUp() override { + data_size = 1024; + data = malloc(data_size); + } + + void TearDown() override { + if (data != nullptr) { + free(data); + data = nullptr; + } + } + + void* data; + size_t data_size; + hardware::Device device{hardware::DeviceType::CPU}; +}; + +TEST_F(StorageTest, TestConstructor) { + Storage storage(data_size, device); + EXPECT_EQ(storage.SizeBytes(), data_size); + EXPECT_EQ(storage.GetDevice().type, device.type); + EXPECT_TRUE(storage.CheckOwnsData()); + EXPECT_EQ(storage.Data(), nullptr); +} + +TEST_F(StorageTest, TestConstructorWithNonOwnedData) { + Storage storage(data, data_size, device); + EXPECT_EQ(storage.SizeBytes(), data_size); + EXPECT_EQ(storage.GetDevice().type, device.type); + EXPECT_FALSE(storage.CheckOwnsData()); + EXPECT_EQ(storage.Data(), data); +} + +TEST_F(StorageTest, TestResize) { + Storage storage(data_size, device); + storage.Resize(2048); + EXPECT_EQ(storage.SizeBytes(), 2048); + EXPECT_EQ(storage.Data(), nullptr); +} + +TEST_F(StorageTest, TestAllocate) { + Storage storage(data, data_size, device); + storage.Resize(2048); + EXPECT_FALSE(storage.CheckOwnsData()); + EXPECT_EQ(storage.Data(), data); + + storage.AllocateMemory(); + EXPECT_TRUE(storage.CheckOwnsData()); + EXPECT_NE(storage.Data(), data); + EXPECT_NE(storage.Data(), nullptr); + + storage.FreeMemory(); + EXPECT_EQ(storage.Data(), nullptr); + EXPECT_FALSE(storage.CheckOwnsData()); +} + +TEST_F(StorageTest, TestDoubleAllocate) { + Storage storage(data_size, device); + storage.AllocateMemory(); + + void *dataPtr = storage.Data(); + EXPECT_THROW(storage.AllocateMemory(), std::runtime_error); + EXPECT_EQ(storage.Data(), dataPtr); +} + +TEST_F(StorageTest, TestFreeNonOwnedData) { + Storage storage(data, data_size, device); + EXPECT_THROW(storage.FreeMemory(), std::runtime_error); + EXPECT_EQ(storage.Data(), data); +} + +TEST_F(StorageTest, TestRelease) { + Storage storage(data_size, device); + storage.AllocateMemory(); + + void *dataPtr = storage.Data(); + void *releasePtr = storage.Release(); + EXPECT_EQ(dataPtr, releasePtr); + EXPECT_EQ(storage.Data(), nullptr); + EXPECT_FALSE(storage.CheckOwnsData()); + + free(releasePtr); +} + +TEST_F(StorageTest, TestDestructorWithNonOwnedData) { + void* dataPtr = malloc(512); + { + Storage storage(dataPtr, 512, device); + } + EXPECT_NO_THROW(free(dataPtr)); +} + +} // namespace ir +} // namespace mrt diff --git a/tests/ut/cpp/run_test.sh b/tests/ut/cpp/run_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..074f1ffc90e4400d00adc8bf982d9bd93066c5a5 --- /dev/null +++ b/tests/ut/cpp/run_test.sh @@ -0,0 +1,39 @@ +# Run UT testcases +set -e + +BASEPATH=$( + cd "$(dirname "$0")" + pwd +) +PROJECT_PATH=${BASEPATH}/../../.. +if [ $BUILD_PATH ]; then + echo "BUILD_PATH = $BUILD_PATH" +else + BUILD_PATH=${PROJECT_PATH}/build + echo "BUILD_PATH = $BUILD_PATH" +fi +cd ${BUILD_PATH}/tests/ut/cpp + +TEST_CASES=( + "./ut_storage_test_obj" + "./hardware_cpu_test_obj" +) + +set +e + +RET=0 +echo "==============================" +for test_case in "${TEST_CASES[@]}"; do + echo "=== Running $test_case ===" + $test_case + status=$? + if [ $status != 0 ]; then + RET=$status + exit $RET + fi +done + +echo "All testcases completed." +echo "==============================" +cd - +exit $RET