Skip to content

Commit

Permalink
[2022.3] Safe plugins loading (#21037)
Browse files Browse the repository at this point in the history
* [Core] Safe loading of default plugins (#15073)

* Fix "(un)register_plugin(s)" C and Py tests (#15291)

* Update test in order to save behaviour
  • Loading branch information
vurusovs authored Nov 14, 2023
1 parent 8af1f18 commit 9839b55
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 162 deletions.
48 changes: 9 additions & 39 deletions src/bindings/c/tests/ie_c_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down
51 changes: 24 additions & 27 deletions src/bindings/python/tests/test_runtime/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# SPDX-License-Identifier: Apache-2.0

import pytest
import sys
import numpy as np
import os
from pathlib import Path
Expand All @@ -28,7 +29,6 @@
generate_image,
generate_relu_compiled_model,
get_relu_model,
generate_lib_name,
plugins_path,
)

Expand Down Expand Up @@ -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"
)

with pytest.raises(RuntimeError) as e:
core.get_versions(device)
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):
core = Core()
# Trigger plugin loading
core.get_versions(device)
# Unload plugin
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)
)


@pytest.mark.template_plugin()
Expand Down
25 changes: 2 additions & 23 deletions src/bindings/python/tests/test_utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import pytest

from pathlib import Path
from platform import processor

import openvino
import openvino.runtime.opset8 as ops
Expand All @@ -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"""<ie>
<plugins>
<plugin location="{full_lib_name}" name="CUSTOM">
<plugin location="{lib_path}" name="{device}">
</plugin>
</plugins>
</ie>"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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):
Expand Down
3 changes: 3 additions & 0 deletions src/common/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
$<BUILD_INTERFACE:${UTIL_INCLUDE_DIR}>)

Expand Down
31 changes: 30 additions & 1 deletion src/common/util/include/openvino/util/file_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -242,6 +251,26 @@ inline std::basic_string<C> make_plugin_library_name(const std::basic_string<C>&
FileTraits<C>::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
Expand Down
Loading

0 comments on commit 9839b55

Please sign in to comment.