diff --git a/tests/appverifier_tests/.clang-format b/tests/appverifier_tests/.clang-format new file mode 100644 index 00000000000..ebe747b7838 --- /dev/null +++ b/tests/appverifier_tests/.clang-format @@ -0,0 +1,28 @@ +BasedOnStyle: Google +IndentWidth: 4 +UseTab: Never +ColumnLimit: 120 + +Language: Cpp +Standard: Cpp11 + +AccessModifierOffset: -4 +AlignConsecutiveMacros: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +AlwaysBreakBeforeMultilineStrings: false +BinPackArguments: false +BinPackParameters: false +CommentPragmas: '^#' +DerivePointerAlignment: false +FixNamespaceComments: true +IndentCaseLabels: false +IndentPPDirectives: AfterHash +ForEachMacros: + - foreach + - FOREACH_CHILD diff --git a/tests/appverifier_tests/CMakeLists.txt b/tests/appverifier_tests/CMakeLists.txt new file mode 100644 index 00000000000..29cfcfa7535 --- /dev/null +++ b/tests/appverifier_tests/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 2018-2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.13) + +project(appverifier_tests) + +if(NOT WIN32) + message(FATAL_ERROR "This test only supports windows OS") +endif() + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "CMake build type") +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release" "Debug" "RelWithDebInfo" "MinSizeRel") + +set(OpenVINO_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../") +set(ENABLE_CLANG_FORMAT ON) +find_package(OpenVINODeveloperScripts REQUIRED + PATHS "${OpenVINO_SOURCE_DIR}/cmake/developer_package" + NO_CMAKE_FIND_ROOT_PATH + NO_DEFAULT_PATH) + +# Define directory where artifacts will be placed +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") +set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") +set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") + +add_subdirectory(thread_local) +add_subdirectory(appverifier_tests) diff --git a/tests/appverifier_tests/README.md b/tests/appverifier_tests/README.md new file mode 100644 index 00000000000..788865c6540 --- /dev/null +++ b/tests/appverifier_tests/README.md @@ -0,0 +1,31 @@ +# AppVerifier Tests Suite + +This test suite is used to detect whether AppVerifier will report a memory leak. + +## Getting Started + +AppVerifier tests are based on the googletest framework. You can filter tests with +`--gtest_filter` and explore tests available with `--gtest_list_tests` options. + +### Pre-requisites + +- Windows OS to build the tests. + +### Building Tests + +To build the tests, you need to have OpenVINO™ installed or build from source. +Before build the tests, open a terminal, set OpenVINO™ environment, and after that +run the commands below: +``` bash +/setupvars.bat +mkdir build && cd build +cmake .. && cmake --build . --config Release -j8 +``` + +### Running Tests + +``` bash +.\test\Release\ov_appverifier_tests.exe +``` + +This test can be run directly using the above command, but if you want to detect whether there is a memory leak, the test executable file need to be added in AppVerifier (refer to https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/application-verifier-testing-applications) before running the above command. diff --git a/tests/appverifier_tests/appverifier_tests/CMakeLists.txt b/tests/appverifier_tests/appverifier_tests/CMakeLists.txt new file mode 100644 index 00000000000..1a5e38d6018 --- /dev/null +++ b/tests/appverifier_tests/appverifier_tests/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (C) 2018-2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(TARGET_NAME ov_appverifier_tests) + +file (GLOB_RECURSE SRC *.cpp) +file (GLOB_RECURSE HDR *.h) + +# Create library file from sources. +add_executable(${TARGET_NAME} ${HDR} ${SRC}) + +target_link_libraries(${TARGET_NAME} + PUBLIC + gtest + pugixml + gflags + PRIVATE + gtest_main) + +ov_add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) diff --git a/tests/appverifier_tests/appverifier_tests/thread_local_test.cpp b/tests/appverifier_tests/appverifier_tests/thread_local_test.cpp new file mode 100644 index 00000000000..e2602ce8f11 --- /dev/null +++ b/tests/appverifier_tests/appverifier_tests/thread_local_test.cpp @@ -0,0 +1,109 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include +#include + +#include +#include + +typedef void (*TestFunc)(const std::string&); + +class ThreadLocalTest : public ::testing::Test, public ::testing::WithParamInterface { +public: + void SetUp() { + target_device = GetParam(); + } + + static std::string getTestCaseName(testing::TestParamInfo obj) { + return obj.param; + } + +public: + std::string target_device = ""; +}; + +TEST(LoadLibraryTest, load_free_library) { + std::promise free_promise; + std::future free_future = free_promise.get_future(); + std::promise thread_exit_promise; + std::future thread_exit_future = thread_exit_promise.get_future(); + auto shared_object = LoadLibraryA("openvino.dll"); + if (!shared_object) { + std::cout << "LoadLibrary openvino.dll fail" << std::endl; + return; + } + + std::thread sub_thread = std::thread([&] { + free_promise.set_value(); + thread_exit_future.get(); + }); + free_future.get(); + FreeLibrary(shared_object); + + thread_exit_promise.set_value(); + if (sub_thread.joinable()) { + sub_thread.join(); + } +} + +TEST_P(ThreadLocalTest, get_property_test) { + auto shared_object = LoadLibraryA("ov_thread_local.dll"); + if (!shared_object) { + std::cout << "LoadLibrary ov_thread_local.dll fail" << std::endl; + return; + } + auto procAddr = reinterpret_cast(GetProcAddress(shared_object, "core_get_property_test")); + procAddr(target_device); + FreeLibrary(shared_object); +} + +TEST_P(ThreadLocalTest, infer_test) { + auto shared_object = LoadLibraryA("ov_thread_local.dll"); + if (!shared_object) { + std::cout << "LoadLibrary ov_thread_local.dll fail" << std::endl; + return; + } + auto procAddr = reinterpret_cast(GetProcAddress(shared_object, "core_infer_test")); + procAddr(target_device); + FreeLibrary(shared_object); +} + +void process_sub_thread(const std::string& func_name, const std::string& target_device) { + auto shared_object = LoadLibraryA("ov_thread_local.dll"); + if (!shared_object) { + std::cout << "LoadLibrary ov_thread_local.dll fail" << std::endl; + return; + } + auto procAddr = reinterpret_cast(GetProcAddress(shared_object, func_name.c_str())); + std::promise free_promise; + std::future free_future = free_promise.get_future(); + std::promise thread_exit_promise; + std::future thread_exit_future = thread_exit_promise.get_future(); + std::thread sub_thread = std::thread([&] { + procAddr(target_device); + free_promise.set_value(); + thread_exit_future.get(); + }); + + free_future.get(); + FreeLibrary(shared_object); + + thread_exit_promise.set_value(); + if (sub_thread.joinable()) { + sub_thread.join(); + } +} + +TEST_P(ThreadLocalTest, get_property_test_subthread) { + process_sub_thread("core_get_property_test", target_device); +} + +TEST_P(ThreadLocalTest, infer_test_subthread) { + process_sub_thread("core_infer_test", target_device); +} + +INSTANTIATE_TEST_SUITE_P(OV_ThreadLocalTests, + ThreadLocalTest, + ::testing::Values("CPU", "GPU"), + ThreadLocalTest::getTestCaseName); diff --git a/tests/appverifier_tests/thread_local/CMakeLists.txt b/tests/appverifier_tests/thread_local/CMakeLists.txt new file mode 100644 index 00000000000..3f4fc39fe27 --- /dev/null +++ b/tests/appverifier_tests/thread_local/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2018-2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(TARGET_NAME ov_thread_local) + +# Search OpenVINO Runtime installed +find_package(PkgConfig QUIET) +# TODO: fix cross-compilation later +if(PkgConfig_FOUND AND NOT CMAKE_CROSSCOMPILING AND CMAKE_BUILD_TYPE STREQUAL "Release") + pkg_search_module(openvino REQUIRED + IMPORTED_TARGET + openvino) + set(ov_link_libraries PkgConfig::openvino) +else() + find_package(OpenVINO REQUIRED COMPONENTS Runtime) + set(ov_link_libraries openvino::runtime) +endif() + +file (GLOB_RECURSE SRC *.cpp) +file (GLOB_RECURSE HDR *.h) + +add_library(${TARGET_NAME} SHARED ${SRC} ${HDR}) + +target_include_directories(${TARGET_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +add_subdirectory(${OpenVINO_SOURCE_DIR}/thirdparty/gflags + ${CMAKE_CURRENT_BINARY_DIR}/gflags_build + EXCLUDE_FROM_ALL) +add_subdirectory(${OpenVINO_SOURCE_DIR}/thirdparty/gtest + ${CMAKE_CURRENT_BINARY_DIR}/gtest_build + EXCLUDE_FROM_ALL) +add_subdirectory(${OpenVINO_SOURCE_DIR}/thirdparty/pugixml + ${CMAKE_CURRENT_BINARY_DIR}/pugixml_build + EXCLUDE_FROM_ALL) +add_subdirectory("${OpenVINO_SOURCE_DIR}/tests/lib" tests_shared_lib) +target_link_libraries(${TARGET_NAME} PUBLIC tests_shared_lib) + +ov_add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) diff --git a/tests/appverifier_tests/thread_local/include/thread_local.hpp b/tests/appverifier_tests/thread_local/include/thread_local.hpp new file mode 100644 index 00000000000..b1902a57b73 --- /dev/null +++ b/tests/appverifier_tests/thread_local/include/thread_local.hpp @@ -0,0 +1,8 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include +#include + +extern "C" __declspec(dllexport) void core_get_property_test(const std::string& target_device); +extern "C" __declspec(dllexport) void core_infer_test(const std::string& target_device); diff --git a/tests/appverifier_tests/thread_local/src/thread_local.cpp b/tests/appverifier_tests/thread_local/src/thread_local.cpp new file mode 100644 index 00000000000..554230b4a63 --- /dev/null +++ b/tests/appverifier_tests/thread_local/src/thread_local.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include "thread_local.hpp" + +#include +#include +#include + +#include "openvino/core/model.hpp" +#include "openvino/core/node_vector.hpp" +#include "openvino/core/type/element_type.hpp" +#include "openvino/op/concat.hpp" +#include "openvino/op/constant.hpp" +#include "openvino/op/reshape.hpp" +#include "openvino/op/split.hpp" +#include "openvino/openvino.hpp" +#include "openvino/runtime/properties.hpp" + +std::shared_ptr make_split_concat(std::vector inputShape = {1, 4, 24, 24}, + ov::element::Type_t type = ov::element::Type_t::f32); + +void core_get_property_test(const std::string& target_device) { + std::promise call_finish_promise; + auto call_finish_future = call_finish_promise.get_future(); + std::promise thread_exit_promise; + auto thread_exit_future = thread_exit_promise.get_future(); + std::thread sub_thread; + { + ov::Core ie; + sub_thread = std::thread([&] { + ie.get_property(target_device, ov::supported_properties); + call_finish_promise.set_value(); + thread_exit_future.get(); + }); + call_finish_future.get(); + } + thread_exit_promise.set_value(); + if (sub_thread.joinable()) { + sub_thread.join(); + } +} + +std::shared_ptr make_split_concat(std::vector inputShape, ov::element::Type_t type) { + auto param1 = std::make_shared(type, ov::Shape{inputShape}); + param1->set_friendly_name("Param1"); + param1->output(0).get_tensor().set_names({"data1"}); + auto axis_node = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{}, {1}); + auto split = std::make_shared(param1, axis_node, 2); + split->set_friendly_name("Split"); + split->output(0).get_tensor().set_names({"tensor_split_1"}); + split->output(1).get_tensor().set_names({"tensor_split_2"}); + + auto concat = std::make_shared(ov::OutputVector{split->output(0), split->output(1)}, 1); + concat->set_friendly_name("Concat_op"); + concat->output(0).get_tensor().set_names({"Concat"}); + auto result = std::make_shared(concat); + result->set_friendly_name("Result"); + auto model_ptr = std::make_shared(ov::ResultVector{result}, ov::ParameterVector{param1}); + model_ptr->set_friendly_name("SplitConcat"); + return model_ptr; +} + +void core_infer_test(const std::string& target_device) { + std::promise call_finish_promise; + std::future call_finish_future = call_finish_promise.get_future(); + std::promise thread_exit_promise; + std::future thread_exit_future = thread_exit_promise.get_future(); + std::thread sub_thread; + auto actualNetwork = make_split_concat(); + { + ov::Core ie; + sub_thread = std::thread([&] { + auto net = ie.compile_model(actualNetwork, target_device); + auto infer_req = net.create_infer_request(); + ie.get_property(target_device, ov::supported_properties); + infer_req.infer(); + call_finish_promise.set_value(); + thread_exit_future.get(); + }); + call_finish_future.get(); + } + thread_exit_promise.set_value(); + if (sub_thread.joinable()) { + sub_thread.join(); + } +}