diff --git a/src/bindings/c/tests/ie_c_api_test.cpp b/src/bindings/c/tests/ie_c_api_test.cpp index 55f783f5f21..129cfcb0322 100644 --- a/src/bindings/c/tests/ie_c_api_test.cpp +++ b/src/bindings/c/tests/ie_c_api_test.cpp @@ -127,21 +127,10 @@ TEST(ie_core_register_plugin, registerPlugin) { IE_ASSERT_OK(ie_core_create("", &core)); ASSERT_NE(nullptr, core); - ie_network_t *network = nullptr; - IE_EXPECT_OK(ie_core_read_network(core, xml, bin, &network)); - EXPECT_NE(nullptr, network); - - const char *plugin_name = "openvino_intel_cpu_plugin"; + const char *plugin_name = "test_plugin"; const char *device_name = "BLA"; IE_EXPECT_OK(ie_core_register_plugin(core, plugin_name, device_name)); - ie_config_t config = {nullptr, nullptr, nullptr}; - ie_executable_network_t *exe_network = nullptr; - IE_EXPECT_OK(ie_core_load_network(core, network, device_name, &config, &exe_network)); - EXPECT_NE(nullptr, exe_network); - - ie_exec_network_free(&exe_network); - ie_network_free(&network); ie_core_free(&core); } @@ -150,43 +139,24 @@ TEST(ie_core_register_plugins, registerPlugins) { IE_ASSERT_OK(ie_core_create("", &core)); ASSERT_NE(nullptr, core); - ie_network_t *network = nullptr; - IE_EXPECT_OK(ie_core_read_network(core, xml, bin, &network)); - EXPECT_NE(nullptr, network); - IE_EXPECT_OK(ie_core_register_plugins(core, plugins_xml)); - ie_config_t config = {nullptr, nullptr, nullptr}; - const char *device_name = "CUSTOM"; - ie_executable_network_t *exe_network = nullptr; - IE_EXPECT_OK(ie_core_load_network(core, network, device_name, &config, &exe_network)); - EXPECT_NE(nullptr, exe_network); - - ie_exec_network_free(&exe_network); - ie_network_free(&network); ie_core_free(&core); } -TEST(ie_core_unregister_plugin, unregisterPlugin) { +TEST(ie_core_unload_plugin, unloadPlugin) { ie_core_t *core = nullptr; - IE_ASSERT_OK(ie_core_create(plugins_xml, &core)); + IE_ASSERT_OK(ie_core_create("", &core)); ASSERT_NE(nullptr, core); - ie_network_t *network = nullptr; - IE_EXPECT_OK(ie_core_read_network(core, xml, bin, &network)); - EXPECT_NE(nullptr, network); - - ie_config_t config = {nullptr, nullptr, nullptr}; - const char *device_name = "CUSTOM"; - ie_executable_network_t *exe_network = nullptr; - IE_EXPECT_OK(ie_core_load_network(core, network, device_name, &config, &exe_network)); - EXPECT_NE(nullptr, exe_network); - - ie_exec_network_free(&exe_network); - ie_network_free(&network); - + const char *device_name = "CPU"; + ie_core_versions_t versions = {0}; + // Trigger plugin loading + IE_EXPECT_OK(ie_core_get_versions(core, device_name, &versions)); + // Unload plugin IE_EXPECT_OK(ie_core_unregister_plugin(core, device_name)); + ie_core_versions_free(&versions); ie_core_free(&core); } diff --git a/src/bindings/python/tests/test_runtime/test_core.py b/src/bindings/python/tests/test_runtime/test_core.py index dd46d96a5e7..73bed6fcdec 100644 --- a/src/bindings/python/tests/test_runtime/test_core.py +++ b/src/bindings/python/tests/test_runtime/test_core.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest +import sys import numpy as np import os from pathlib import Path @@ -28,7 +29,6 @@ from tests.test_utils.test_utils import ( generate_image, generate_relu_compiled_model, get_relu_model, - generate_lib_name, plugins_path, ) @@ -257,43 +257,40 @@ def test_query_model(device): @pytest.mark.dynamic_library() -def test_register_plugin(device): +def test_register_plugin(): + device = "TEST_DEVICE" + lib_name = "test_plugin" + full_lib_name = lib_name + ".dll" if sys.platform == "win32" else "lib" + lib_name + ".so" + core = Core() - full_device_name = core.get_property(device, "FULL_DEVICE_NAME") - lib_name = generate_lib_name(device, full_device_name) - core.register_plugin(lib_name, "BLA") - model = core.read_model(model=test_net_xml, weights=test_net_bin) - compiled_model = core.compile_model(model, "BLA") - assert isinstance(compiled_model, CompiledModel), "Cannot load the network to the registered plugin with name 'BLA'" + core.register_plugin(lib_name, device) + with pytest.raises(RuntimeError) as e: + core.get_versions(device) + assert f"Cannot load library '{full_lib_name}'" in str(e.value) @pytest.mark.dynamic_library() -def test_register_plugins(device): +def test_register_plugins(): + device = "TEST_DEVICE" + lib_name = "test_plugin" + full_lib_name = lib_name + ".dll" if sys.platform == "win32" else "lib" + lib_name + ".so" + plugins_xml = plugins_path(device, full_lib_name) + core = Core() - full_device_name = core.get_property(device, "FULL_DEVICE_NAME") - plugins_xml = plugins_path(device, full_device_name) core.register_plugins(plugins_xml) - model = core.read_model(model=test_net_xml, weights=test_net_bin) - compiled_model = core.compile_model(model, "CUSTOM") os.remove(plugins_xml) - assert isinstance(compiled_model, CompiledModel), ( - "Cannot load the network to " - "the registered plugin with name 'CUSTOM' " - "registered in the XML file" - ) - -@pytest.mark.skip(reason="Need to figure out if it's expected behaviour (fails with C++ API as well") -def test_unregister_plugin(device): - core = Core() - core.unload_plugin(device) - model = core.read_model(model=test_net_xml, weights=test_net_bin) with pytest.raises(RuntimeError) as e: - core.load_network(model, device) - assert ( - f"Device with '{device}' name is not registered in the OpenVINO Runtime" - in str(e.value) - ) + core.get_versions(device) + assert f"Cannot load library '{full_lib_name}'" in str(e.value) + + +def test_unload_plugin(device): + core = Core() + # Trigger plugin loading + core.get_versions(device) + # Unload plugin + core.unload_plugin(device) @pytest.mark.template_plugin() diff --git a/src/bindings/python/tests/test_utils/test_utils.py b/src/bindings/python/tests/test_utils/test_utils.py index b64432ccd3b..de31ff88779 100644 --- a/src/bindings/python/tests/test_utils/test_utils.py +++ b/src/bindings/python/tests/test_utils/test_utils.py @@ -10,7 +10,6 @@ import numpy as np import pytest from pathlib import Path -from platform import processor import openvino import openvino.runtime.opset8 as ops @@ -28,30 +27,10 @@ def test_compare_models(): print("openvino.test_utils.compare_models is not available") # noqa: T201 -def generate_lib_name(device, full_device_name): - lib_name = "" - arch = processor() - if arch == "x86_64" or "Intel" in full_device_name or device in ["GNA", "HDDL", "MYRIAD", "VPUX"]: - lib_name = "openvino_intel_" + device.lower() + "_plugin" - elif arch != "x86_64" and device == "CPU": - lib_name = "openvino_arm_cpu_plugin" - elif device in ["HETERO", "MULTI", "AUTO"]: - lib_name = "openvino_" + device.lower() + "_plugin" - return lib_name - - -def plugins_path(device, full_device_name): - lib_name = generate_lib_name(device, full_device_name) - full_lib_name = "" - - if sys.platform == "win32": - full_lib_name = lib_name + ".dll" - else: - full_lib_name = "lib" + lib_name + ".so" - +def plugins_path(device, lib_path): plugin_xml = f""" - + """ diff --git a/src/bindings/python/tests_compatibility/test_inference_engine/test_IECore.py b/src/bindings/python/tests_compatibility/test_inference_engine/test_IECore.py index 9e86980a029..edda335c011 100644 --- a/src/bindings/python/tests_compatibility/test_inference_engine/test_IECore.py +++ b/src/bindings/python/tests_compatibility/test_inference_engine/test_IECore.py @@ -85,16 +85,16 @@ def test_query_network(device): @pytest.mark.dynamic_library -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_register_plugin(): - ie = IECore() - if ie.get_metric("CPU", "FULL_DEVICE_NAME") == "arm_compute::NEON": - pytest.skip("Can't run on ARM plugin due-to openvino_intel_cpu_plugin specific test") - ie.register_plugin("openvino_intel_cpu_plugin", "BLA") - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - exec_net = ie.load_network(net, "BLA") - assert isinstance(exec_net, ExecutableNetwork), "Cannot load the network to the registered plugin with name 'BLA'" + device = "TEST_DEVICE" + lib_name = "test_plugin" + full_lib_name = lib_name + ".dll" if sys.platform == "win32" else "lib" + lib_name + ".so" + ie = IECore() + ie.register_plugin(lib_name, device) + with pytest.raises(RuntimeError) as e: + ie.get_versions(device) + assert f"Cannot load library '{full_lib_name}'" in str(e.value) @pytest.mark.dynamic_library def test_register_plugins(): @@ -119,17 +119,15 @@ def test_register_plugins(): with pytest.raises(RuntimeError) as e: ie.get_versions(device) - assert f"Cannot load library '{full_lib_name}" in str(e.value) + assert f"Cannot load library '{full_lib_name}'" in str(e.value) -@pytest.mark.skip(reason="Need to figure out if it's expected behaviour (fails with C++ API as well") -def test_unregister_plugin(device): +def test_unload_plugin(device): ie = IECore() + # Trigger plugin loading + ie.get_versions(device) + # Unload plugin ie.unregister_plugin(device) - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - with pytest.raises(RuntimeError) as e: - ie.load_network(net, device) - assert f"Device with '{device}' name is not registered in the OpenVINO Runtime" in str(e.value) def test_available_devices(device): diff --git a/src/common/util/CMakeLists.txt b/src/common/util/CMakeLists.txt index 618f2734324..ffd0b982623 100644 --- a/src/common/util/CMakeLists.txt +++ b/src/common/util/CMakeLists.txt @@ -33,6 +33,9 @@ add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS}) add_library(openvino::util ALIAS ${TARGET_NAME}) target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_DL_LIBS}) +if (WIN32) + target_link_libraries(${TARGET_NAME} PRIVATE Shlwapi) +endif() target_include_directories(${TARGET_NAME} PUBLIC $) diff --git a/src/common/util/include/openvino/util/file_util.hpp b/src/common/util/include/openvino/util/file_util.hpp index d2f2e00ff60..00d8dbe073c 100644 --- a/src/common/util/include/openvino/util/file_util.hpp +++ b/src/common/util/include/openvino/util/file_util.hpp @@ -97,9 +97,18 @@ std::string get_file_name(const std::string& path); * @brief Interface function to get absolute path of file * @param path - path to file, can be relative to current working directory * @return Absolute path of file - * @throw runtime_error if any error occurred + * @throw runtime_error if absolute path can't be resolved */ std::string get_absolute_file_path(const std::string& path); + +/** + * @brief Interface function to check path to file is absolute or not + * @param path - path to file, can be relative to current working directory + * @return True if path is absolute and False otherwise + * @throw runtime_error if any error occurred + */ +bool is_absolute_file_path(const std::string& path); + /** * @brief Interface function to create directorty recursively by given path * @param path - path to file, can be relative to current working directory @@ -242,6 +251,26 @@ inline std::basic_string make_plugin_library_name(const std::basic_string& FileTraits::library_ext(); } +/** + * @brief Format plugin path (canonicalize, complete to absolute or complete to file name) for further + * dynamic loading by OS + * @param plugin - Path (absolute or relative) or name of a plugin. Depending on platform, `plugin` is wrapped with + * shared library suffix and prefix to identify library full name + * @return absolute path or file name with extension (to be found in ENV) + */ +FilePath get_plugin_path(const std::string& plugin); + +/** + * @brief Format plugin path (canonicalize, complete to absolute or complete to file name) for further + * dynamic loading by OS + * @param plugin - Path (absolute or relative) or name of a plugin. Depending on platform, `plugin` is wrapped with + * shared library suffix and prefix to identify library full name + * @param xml_path - Path (absolute or relative) to XML configuration file + * @param as_abs_only - Bool value, allows return file names or not + * @return absolute path or file name with extension (to be found in ENV) + */ +FilePath get_plugin_path(const std::string& plugin, const std::string& xml_path, bool as_abs_only = false); + /** * @brief load binary data from file * @param path - binary file path to load diff --git a/src/common/util/src/file_util.cpp b/src/common/util/src/file_util.cpp index 97a329ddcdb..78391866c72 100644 --- a/src/common/util/src/file_util.cpp +++ b/src/common/util/src/file_util.cpp @@ -17,6 +17,7 @@ # ifndef NOMINMAX # define NOMINMAX # endif +# include # include # include /// @brief Max length of absolute file path @@ -351,14 +352,26 @@ std::wstring ov::util::string_to_wstring(const std::string& string) { std::string ov::util::get_absolute_file_path(const std::string& path) { std::string absolutePath; absolutePath.resize(MAX_ABS_PATH); - auto absPath = get_absolute_path(&absolutePath[0], path); - if (!absPath) { - std::stringstream ss; - ss << "Can't get absolute file path for [" << path << "], err = " << strerror(errno); - throw std::runtime_error(ss.str()); + std::ignore = get_absolute_path(&absolutePath[0], path); + if (!absolutePath.empty()) { + // on Linux if file does not exist or no access, function will return NULL, but + // `absolutePath` will contain resolved path + absolutePath.resize(absolutePath.find('\0')); + return std::string(absolutePath); } - absolutePath.resize(strlen(absPath)); - return absolutePath; + std::stringstream ss; + ss << "Can't get absolute file path for [" << path << "], err = " << strerror(errno); + throw std::runtime_error(ss.str()); +} + +bool ov::util::is_absolute_file_path(const std::string& path) { + if (path.empty()) + throw std::runtime_error("Provided path is empty"); +#ifdef _WIN32 + return !PathIsRelativeA(path.c_str()); +#else + return path[0] == '/'; +#endif // _WIN32 } void ov::util::create_directory_recursive(const std::string& path) { @@ -458,6 +471,64 @@ std::wstring ov::util::get_ov_lib_path_w() { #endif // OPENVINO_ENABLE_UNICODE_PATH_SUPPORT +ov::util::FilePath ov::util::get_plugin_path(const std::string& plugin) { + // Assume `plugin` may contain: + // 1. /path/to/libexample.so absolute path + // 2. ../path/to/libexample.so path relative to working directory + // 3. example library name - to be converted to 4th case + // 4. libexample.so - path relative to working directory (if exists) or file to be found in ENV + + // For 1-2 cases + if (plugin.find(FileTraits::file_separator) != std::string::npos) + return ov::util::to_file_path(ov::util::get_absolute_file_path(plugin)); + + auto lib_name = plugin; + // For 3rd case - convert to 4th case + if (!ov::util::ends_with(plugin, ov::util::FileTraits::library_ext())) + lib_name = ov::util::make_plugin_library_name({}, plugin); + + // For 4th case + auto lib_path = ov::util::to_file_path(ov::util::get_absolute_file_path(lib_name)); + if (ov::util::file_exists(lib_path)) + return lib_path; + return ov::util::to_file_path(lib_name); +} + +ov::util::FilePath ov::util::get_plugin_path(const std::string& plugin, const std::string& xml_path, bool as_abs_only) { + // Assume `plugin` (from XML "location" record) contains only: + // 1. /path/to/libexample.so absolute path + // 2. ../path/to/libexample.so path relative to XML directory + // 3. example library name - to be converted to 4th case + // 4. libexample.so - path relative to XML directory (if exists) or file to be found in ENV + // (if `as_abs_only` is false) + + // For 1st case + if (ov::util::is_absolute_file_path(plugin)) + return ov::util::to_file_path(plugin); + + auto xml_path_ = xml_path; + if (xml_path.find(ov::util::FileTraits::file_separator) == std::string::npos) + xml_path_ = ov::util::path_join({std::string("."), xml_path}); // treat plugins.xml as CWD/plugins.xml + + // For 2nd case + if (plugin.find(ov::util::FileTraits::file_separator) != std::string::npos) { + auto path_ = ov::util::path_join({ov::util::get_directory(xml_path_), plugin}); + return ov::util::to_file_path(ov::util::get_absolute_file_path(path_)); // canonicalize path + } + + auto lib_file_name = plugin; + // For 3rd case - convert to 4th case + if (!ov::util::ends_with(plugin, ov::util::FileTraits::library_ext())) + lib_file_name = ov::util::make_plugin_library_name({}, plugin); + + // For 4th case + auto lib_path = ov::util::path_join({ov::util::get_directory(xml_path_), lib_file_name}); + lib_path = ov::util::get_absolute_file_path(lib_path); // canonicalize path + if (as_abs_only || ov::util::file_exists(lib_path)) + return ov::util::to_file_path(lib_path); + return ov::util::to_file_path(lib_file_name); +} + std::vector ov::util::load_binary(const std::string& path) { #if defined(OPENVINO_ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) std::wstring widefilename = ov::util::string_to_wstring(path); diff --git a/src/common/util/src/os/lin/lin_shared_object_loader.cpp b/src/common/util/src/os/lin/lin_shared_object_loader.cpp index 4d9cba447f0..ad97072c6d6 100644 --- a/src/common/util/src/os/lin/lin_shared_object_loader.cpp +++ b/src/common/util/src/os/lin/lin_shared_object_loader.cpp @@ -26,7 +26,7 @@ std::shared_ptr load_shared_object(const char* path) { }}; if (!shared_object) { std::stringstream ss; - ss << "Cannot load library '" << path; + ss << "Cannot load library '" << path << "'"; if (auto error = dlerror()) { ss << ": " << error; } diff --git a/src/inference/src/ie_core.cpp b/src/inference/src/ie_core.cpp index fadca189df9..26a44c6dfdf 100644 --- a/src/inference/src/ie_core.cpp +++ b/src/inference/src/ie_core.cpp @@ -109,49 +109,6 @@ std::string resolve_extension_path(const std::string& path) { return retvalue; } -ov::util::FilePath getPluginPath(const std::string& pluginName, bool needAddSuffixes = false) { - const auto ieLibraryPath = ie::getInferenceEngineLibraryPath(); - - auto pluginPath = ov::util::to_file_path(pluginName.c_str()); - - // 0. user can provide a full path - -#ifndef _WIN32 - try { - // dlopen works with absolute paths; otherwise searches from LD_LIBRARY_PATH - pluginPath = ov::util::to_file_path(ov::util::get_absolute_file_path(pluginName)); - } catch (const std::runtime_error&) { - // failed to resolve absolute path; not critical - } -#endif // _WIN32 - - if (FileUtils::fileExist(pluginPath)) - return pluginPath; - - // ov::Core::register_plugin(plugin_name, device_name) case - if (needAddSuffixes) - pluginPath = FileUtils::makePluginLibraryName({}, pluginPath); - - // plugin can be found either: - - // 1. in openvino-X.Y.Z folder relative to libopenvino.so - std::ostringstream str; - str << "openvino-" << OPENVINO_VERSION_MAJOR << "." << OPENVINO_VERSION_MINOR << "." << OPENVINO_VERSION_PATCH; - const auto subFolder = ov::util::to_file_path(str.str()); - - ov::util::FilePath absFilePath = FileUtils::makePath(FileUtils::makePath(ieLibraryPath, subFolder), pluginPath); - if (FileUtils::fileExist(absFilePath)) - return absFilePath; - - // 2. in the openvino.so location - absFilePath = FileUtils::makePath(ieLibraryPath, pluginPath); - if (FileUtils::fileExist(absFilePath)) - return absFilePath; - - // 3. in LD_LIBRARY_PATH on Linux / PATH on Windows - return pluginPath; -} - template Parsed parseDeviceNameIntoConfig(const std::string& deviceName, const std::map& config = {}) { auto config_ = config; @@ -571,8 +528,9 @@ public: * @brief Register plugins for devices which are located in .xml configuration file. * @note The function supports UNICODE path * @param xmlConfigFile An .xml configuraion with device / plugin information + * @param ByAbsPath A boolean value - register plugins by absolute file path or not */ - void RegisterPluginsInRegistry(const std::string& xmlConfigFile) { + void RegisterPluginsInRegistry(const std::string& xmlConfigFile, const bool& ByAbsPath = false) { std::lock_guard lock(get_mutex()); auto parse_result = ParseXml(xmlConfigFile.c_str()); @@ -588,7 +546,8 @@ public: FOREACH_CHILD (pluginNode, devicesNode, "plugin") { std::string deviceName = GetStrAttr(pluginNode, "name"); - ov::util::FilePath pluginPath = getPluginPath(GetStrAttr(pluginNode, "location")); + ov::util::FilePath pluginPath = + ov::util::get_plugin_path(GetStrAttr(pluginNode, "location"), xmlConfigFile, ByAbsPath); if (deviceName.find('.') != std::string::npos) { IE_THROW() << "Device name must not contain dot '.' symbol"; @@ -1286,7 +1245,7 @@ public: IE_THROW() << "Device name must not contain dot '.' symbol"; } - PluginDescriptor desc{getPluginPath(pluginName, true)}; + PluginDescriptor desc{ov::util::get_plugin_path(pluginName)}; pluginRegistry[deviceName] = desc; add_mutex(deviceName); } @@ -1665,7 +1624,9 @@ Core::Core(const std::string& xmlConfigFile) { #ifdef OPENVINO_STATIC_LIBRARY _impl->RegisterPluginsInRegistry(::getStaticPluginsRegistry()); #else - RegisterPlugins(ov::findPluginXML(xmlConfigFile)); + // If XML is default, load default plugins by absolute paths + auto loadByAbsPath = xmlConfigFile.empty(); + _impl->RegisterPluginsInRegistry(ov::findPluginXML(xmlConfigFile), loadByAbsPath); #endif } @@ -1943,9 +1904,13 @@ Core::Core(const std::string& xmlConfigFile) { _impl = std::make_shared(); #ifdef OPENVINO_STATIC_LIBRARY - _impl->RegisterPluginsInRegistry(::getStaticPluginsRegistry()); + OV_CORE_CALL_STATEMENT(_impl->RegisterPluginsInRegistry(::getStaticPluginsRegistry());) #else - register_plugins(findPluginXML(xmlConfigFile)); + OV_CORE_CALL_STATEMENT({ + // If XML is default, load default plugins by absolute paths + auto loadByAbsPath = xmlConfigFile.empty(); + _impl->RegisterPluginsInRegistry(findPluginXML(xmlConfigFile), loadByAbsPath); + }) #endif } diff --git a/src/inference/tests/unit/CMakeLists.txt b/src/inference/tests/unit/CMakeLists.txt index 8bd1ddcb0b6..63f42720b17 100644 --- a/src/inference/tests/unit/CMakeLists.txt +++ b/src/inference/tests/unit/CMakeLists.txt @@ -32,6 +32,8 @@ ov_add_test_target( LINK_LIBRARIES unitTestUtils INCLUDES + # for static ie_plugins.hpp + "${CMAKE_BINARY_DIR}/src/inference/" LABELS OV ) diff --git a/src/inference/tests/unit/core.cpp b/src/inference/tests/unit/core.cpp new file mode 100644 index 00000000000..a865f90f961 --- /dev/null +++ b/src/inference/tests/unit/core.cpp @@ -0,0 +1,129 @@ +// Copyright (C) 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "openvino/runtime/core.hpp" + +#include +#include + +#include + +#include "common_test_utils/test_assertions.hpp" +#include "file_utils.h" +#include "openvino/util/file_util.hpp" + +using namespace testing; +using namespace ov::util; + +TEST(CoreTests, ThrowOnRegisterPluginTwice) { + ov::Core core; + core.register_plugin("test_plugin", "TEST_DEVICE"); + OV_EXPECT_THROW(core.register_plugin("test_plugin", "TEST_DEVICE"), + ov::Exception, + ::testing::HasSubstr("Device with \"TEST_DEVICE\" is already registered in the OpenVINO Runtime")); +} + +TEST(CoreTests, NoThrowOnRegisterPluginsTwice) { + ov::Core core; + + auto getPluginXml = [&]() -> std::string { + std::string pluginsXML = "test_plugins.xml"; + std::ofstream file(pluginsXML); + file << ""; + file.flush(); + file.close(); + return pluginsXML; + }; + + core.register_plugins(getPluginXml()); + EXPECT_NO_THROW(core.register_plugins(getPluginXml())); +} + +TEST(CoreTests_getPluginPath_FromXML, UseAbsPathAsIs) { + auto xmlPath = "path_to_plugins.xml"; + auto libPath = ov::util::get_absolute_file_path("test_name.ext"); // CWD/test_name.ext + for (auto asAbsOnly : std::vector{true, false}) { + auto absPath = from_file_path(get_plugin_path(libPath, xmlPath, asAbsOnly)); + EXPECT_TRUE(is_absolute_file_path(absPath)); + EXPECT_STREQ(absPath.c_str(), libPath.c_str()); + } +} + +TEST(CoreTests_getPluginPath_FromXML, ConvertRelativePathAsRelativeToXMLDir) { + auto xmlPath = "path_to_plugins.xml"; + auto libPath = FileUtils::makePath(std::string("."), std::string("test_name.ext")); // ./test_name.ext + for (auto asAbsOnly : std::vector{true, false}) { + auto absPath = from_file_path(get_plugin_path(libPath, xmlPath, asAbsOnly)); // XMLDIR/test_name.ext + EXPECT_TRUE(is_absolute_file_path(absPath)); + + auto refPath = ov::util::get_absolute_file_path(libPath); + EXPECT_STREQ(absPath.c_str(), refPath.c_str()); // XMLDIR/test_name.ext == CWD/test_name.ext + } +} + +TEST(CoreTests_getPluginPath_FromXML, ConvertFileNameToAbsPathIfAsAbsOnly) { + auto xmlPath = "path_to_plugins.xml"; + auto name = "test_name.ext"; // test_name.ext + auto absPath = from_file_path(get_plugin_path(name, xmlPath, true)); // XMLDIR/libtest_name.ext.so + EXPECT_TRUE(is_absolute_file_path(absPath)); + + auto libName = FileUtils::makePluginLibraryName({}, std::string(name)); + auto refPath = ov::util::get_absolute_file_path(libName); + EXPECT_STREQ(absPath.c_str(), refPath.c_str()); // XMLDIR/libtest_name.ext.so == CWD/libtest_name.ext.so +} + +TEST(CoreTests_getPluginPath_FromXML, UseFileNameIfNotAsAbsOnly) { + auto xmlPath = "path_to_plugins.xml"; + auto name = "test_name.ext"; // test_name.ext + auto libName = from_file_path(get_plugin_path(name, xmlPath)); // libtest_name.ext.so + auto refName = FileUtils::makePluginLibraryName({}, std::string(name)); + EXPECT_STREQ(libName.c_str(), refName.c_str()); +} + +TEST(CoreTests_getPluginPath, UseAbsPathAsIs) { + auto libName = FileUtils::makePluginLibraryName({}, std::string("test_name")); // libtest_name.so + auto libPath = ov::util::get_absolute_file_path(libName); + auto absPath = from_file_path(get_plugin_path(libPath)); + EXPECT_TRUE(is_absolute_file_path(absPath)); + EXPECT_STREQ(absPath.c_str(), libPath.c_str()); +} + +TEST(CoreTests_getPluginPath, RelativePathIsFromWorkDir) { + auto libName = FileUtils::makePluginLibraryName(std::string("."), std::string("test_name")); // ./libtest_name.so + auto absPath = from_file_path(get_plugin_path(libName)); + EXPECT_TRUE(is_absolute_file_path(absPath)); + EXPECT_STREQ(absPath.c_str(), get_absolute_file_path(libName).c_str()); +} + +class CoreTests_getPluginPath_Class : public ::testing::Test { +public: + void SetUp() override { + std::ofstream file(libPath); + file << "not empty"; + file.flush(); + file.close(); + } + + void TearDown() override { + std::remove(libPath.c_str()); + } + + std::string libName = FileUtils::makePluginLibraryName({}, std::string("test_name")); // libtest_name.so + std::string libPath = ov::util::get_absolute_file_path(libName); // CWD/libtest_name.so +}; + +TEST_F(CoreTests_getPluginPath_Class, FileNameIsFromWorkDirIfExists) { + auto absPath = from_file_path(get_plugin_path(libName)); // libtest_name.so -> CWD/libtest_name.so + EXPECT_TRUE(is_absolute_file_path(absPath)); + EXPECT_STREQ(absPath.c_str(), get_absolute_file_path(libName).c_str()); +} + +TEST(CoreTests_getPluginPath, UseFileNameAsIsIfNotExistInWorkDir) { + auto libName = "test_name.ext"; + auto absPath = from_file_path(get_plugin_path(libName)); // libtest_name.ext.so -> libtest_name.ext.so + EXPECT_FALSE(is_absolute_file_path(absPath)); + + auto refPath = FileUtils::makePluginLibraryName({}, std::string(libName)); + EXPECT_STREQ(absPath.c_str(), refPath.c_str()); +} \ No newline at end of file