Skip to content

Commit b18ffa1

Browse files
RyanMetcalfeInt8ankitm3k
authored andcommitted
Add OrtEpLibraryOv tests
1 parent af1df0a commit b18ffa1

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#include <filesystem>
2+
#include <gsl/span>
3+
4+
#include "gtest/gtest.h"
5+
#include "core/common/common.h"
6+
#include "core/session/onnxruntime_session_options_config_keys.h"
7+
#include "onnxruntime_cxx_api.h"
8+
#include "api_asserts.h"
9+
#include "core/session/onnxruntime_session_options_config_keys.h"
10+
11+
extern std::unique_ptr<Ort::Env> ort_env;
12+
13+
struct OrtEpLibraryOv : public ::testing::Test {
14+
static const inline std::filesystem::path library_path =
15+
#if _WIN32
16+
"onnxruntime_providers_openvino.dll";
17+
#else
18+
"libonnxruntime_providers_openvino.so";
19+
#endif
20+
static const inline std::string registration_name = "OpenVINOExecutionProvider";
21+
22+
void SetUp() override {
23+
#ifndef _WIN32
24+
GTEST_SKIP() << "Skipping OpenVINO EP tests as the OpenVINO plugin is not built.";
25+
#endif
26+
ort_env->RegisterExecutionProviderLibrary(registration_name.c_str(), library_path.c_str());
27+
}
28+
29+
void TearDown() override {
30+
#ifndef _WIN32
31+
GTEST_SKIP() << "Skipping OpenVINO EP tests as the OpenVINO plugin is not built.";
32+
#endif
33+
ort_env->UnregisterExecutionProviderLibrary(registration_name.c_str());
34+
}
35+
36+
void RunModelWithSession(Ort::Session& session) {
37+
Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
38+
std::vector<int64_t> shape = {3, 2};
39+
std::vector<float> input0_data(6, 2.0f);
40+
std::vector<Ort::Value> ort_inputs;
41+
std::vector<const char*> ort_input_names;
42+
ort_inputs.emplace_back(Ort::Value::CreateTensor<float>(
43+
memory_info, input0_data.data(), input0_data.size(), shape.data(), shape.size()));
44+
ort_input_names.push_back("X");
45+
std::array<const char*, 1> output_names{"Y"};
46+
std::vector<Ort::Value> ort_outputs = session.Run(Ort::RunOptions{nullptr}, ort_input_names.data(), ort_inputs.data(),
47+
ort_inputs.size(), output_names.data(), output_names.size());
48+
Ort::Value& ort_output = ort_outputs[0];
49+
const float* output_data = ort_output.GetTensorData<float>();
50+
gsl::span<const float> output_span(output_data, 6);
51+
EXPECT_THAT(output_span, ::testing::ElementsAre(2, 4, 6, 8, 10, 12));
52+
}
53+
54+
void RunModelWithPluginEp(Ort::SessionOptions& session_options) {
55+
Ort::Session session(*ort_env, ORT_TSTR("testdata/mul_1.onnx"), session_options);
56+
RunModelWithSession(session);
57+
}
58+
59+
void GenerateEpContextOnLegacyPath(std::filesystem::path epctx, bool embed_mode) {
60+
Ort::SessionOptions session_options{};
61+
std::filesystem::remove(epctx);
62+
// Add config option to enable EP context
63+
session_options.SetGraphOptimizationLevel(ORT_DISABLE_ALL);
64+
session_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1");
65+
session_options.AddConfigEntry(kOrtSessionOptionEpContextFilePath, epctx.string().c_str());
66+
session_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, embed_mode ? "1" : "0");
67+
session_options.AppendExecutionProvider_OpenVINO_V2({{"device_type", "CPU"}});
68+
Ort::Session session(*ort_env, ORT_TSTR("testdata/mul_1.onnx"), session_options);
69+
RunModelWithSession(session);
70+
}
71+
72+
void GenerateEpContextOnPluginPath(std::filesystem::path epctx, bool embed_mode) {
73+
Ort::SessionOptions session_options{};
74+
std::filesystem::remove(epctx);
75+
// Add config option to enable EP context
76+
session_options.SetGraphOptimizationLevel(ORT_DISABLE_ALL);
77+
session_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1");
78+
session_options.AddConfigEntry(kOrtSessionOptionEpContextFilePath, epctx.string().c_str());
79+
session_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, embed_mode ? "1" : "0");
80+
Ort::ConstEpDevice plugin_ep_device = GetOvCpuEpDevice();
81+
ASSERT_NE(plugin_ep_device, nullptr);
82+
std::unordered_map<std::string, std::string> ep_options;
83+
session_options.AppendExecutionProvider_V2(*ort_env, std::vector<Ort::ConstEpDevice>{plugin_ep_device}, ep_options);
84+
Ort::Session session(*ort_env, ORT_TSTR("testdata/mul_1.onnx"), session_options);
85+
RunModelWithSession(session);
86+
}
87+
88+
Ort::ConstEpDevice GetOvCpuEpDevice(std::string device_type = "CPU") {
89+
auto ep_devices = ort_env->GetEpDevices();
90+
Ort::ConstEpDevice plugin_ep_device{};
91+
92+
for (Ort::ConstEpDevice& device : ep_devices) {
93+
if (device.Device().Type() == OrtHardwareDeviceType_CPU &&
94+
std::string_view(device.EpName()).find(registration_name) != std::string::npos) {
95+
const auto& meta_kv = device.EpMetadata().GetKeyValuePairs();
96+
auto device_type_it = meta_kv.find("ov_device");
97+
if (device_type_it != meta_kv.end()) {
98+
if (device_type_it->second == device_type) {
99+
plugin_ep_device = device;
100+
break;
101+
}
102+
}
103+
}
104+
}
105+
106+
return plugin_ep_device;
107+
}
108+
};
109+
110+
TEST_F(OrtEpLibraryOv, LoadUnloadPluginLibrary) {
111+
auto ep_devices = ort_env->GetEpDevices();
112+
auto test_cpu_ep_device = GetOvCpuEpDevice();
113+
ASSERT_NE(test_cpu_ep_device, nullptr);
114+
ASSERT_STREQ(test_cpu_ep_device.EpVendor(), "Intel");
115+
Ort::ConstHardwareDevice device = test_cpu_ep_device.Device();
116+
ASSERT_EQ(device.Type(), OrtHardwareDeviceType_CPU);
117+
ASSERT_GE(device.VendorId(), 0);
118+
ASSERT_GE(device.DeviceId(), 0);
119+
ASSERT_NE(device.Vendor(), nullptr);
120+
std::unordered_map<std::string, std::string> ep_metadata_entries = test_cpu_ep_device.EpMetadata().GetKeyValuePairs();
121+
ASSERT_GT(ep_metadata_entries.size(), 0);
122+
ASSERT_GT(ep_metadata_entries.count("ov_device"), 0);
123+
}
124+
125+
TEST_F(OrtEpLibraryOv, MetaDevicesAvailable) {
126+
auto ep_devices = ort_env->GetEpDevices();
127+
auto expected_meta_devices = {"AUTO"};
128+
129+
for (auto& expected_meta_device : expected_meta_devices) {
130+
std::string expected_ep_name = registration_name + "." + expected_meta_device;
131+
auto it = std::find_if(ep_devices.begin(), ep_devices.end(),
132+
[&](Ort::ConstEpDevice& device) {
133+
return std::string_view(device.EpName()).find(expected_ep_name) != std::string::npos;
134+
});
135+
bool meta_device_found = it != ep_devices.end();
136+
ASSERT_TRUE(meta_device_found) << "Expected to find " << expected_ep_name;
137+
}
138+
}
139+
140+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_MulInference) {
141+
auto plugin_ep_device = GetOvCpuEpDevice();
142+
ASSERT_NE(plugin_ep_device, nullptr);
143+
144+
Ort::SessionOptions session_options;
145+
std::unordered_map<std::string, std::string> ep_options;
146+
session_options.AppendExecutionProvider_V2(*ort_env, std::vector<Ort::ConstEpDevice>{plugin_ep_device}, ep_options);
147+
RunModelWithPluginEp(session_options);
148+
}
149+
150+
TEST_F(OrtEpLibraryOv, PluginEp_PreferCpu_MulInference) {
151+
Ort::SessionOptions session_options;
152+
session_options.SetEpSelectionPolicy(OrtExecutionProviderDevicePolicy_PREFER_CPU);
153+
RunModelWithPluginEp(session_options);
154+
}
155+
156+
struct EpCtxTestCases {
157+
const ORTCHAR_T* ctx_filename;
158+
bool embed_mode;
159+
};
160+
161+
static const std::vector<EpCtxTestCases> ep_context_cases = {
162+
{ORT_TSTR("mul_1_ctx_cpu_embed1.onnx"), true},
163+
{ORT_TSTR("mul_1_ctx_cpu_embed0.onnx"), false},
164+
{ORT_TSTR("testdata/mul_1_ctx_cpu_embed0.onnx"), false}};
165+
166+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_cpu_epctx_variants) {
167+
auto plugin_ep_device = GetOvCpuEpDevice();
168+
ASSERT_NE(plugin_ep_device, nullptr);
169+
170+
for (const auto& test_case : ep_context_cases) {
171+
GenerateEpContextOnLegacyPath(test_case.ctx_filename, test_case.embed_mode);
172+
173+
Ort::SessionOptions session_options;
174+
std::unordered_map<std::string, std::string> ep_options;
175+
session_options.AppendExecutionProvider_V2(*ort_env, std::vector<Ort::ConstEpDevice>{plugin_ep_device}, ep_options);
176+
Ort::Session session(*ort_env, test_case.ctx_filename, session_options);
177+
RunModelWithSession(session);
178+
}
179+
}
180+
181+
TEST_F(OrtEpLibraryOv, GenerateEpContextEmbedded) {
182+
GenerateEpContextOnPluginPath(ORT_TSTR("mul_1_ctx_cpu_embed1.onnx"), true);
183+
}
184+
185+
TEST_F(OrtEpLibraryOv, GenerateEpContext) {
186+
GenerateEpContextOnPluginPath(ORT_TSTR("mul_1_ctx_cpu_embed0.onnx"), false);
187+
}
188+
189+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_cpu_epctx_plugin_roundtrip_variants) {
190+
auto plugin_ep_device = GetOvCpuEpDevice();
191+
ASSERT_NE(plugin_ep_device, nullptr);
192+
193+
for (const auto& test_case : ep_context_cases) {
194+
if (test_case.embed_mode) {
195+
// TODO(ericcraw) Re-enable.
196+
// Skip the embed mode until upstream fix.
197+
continue;
198+
}
199+
200+
GenerateEpContextOnPluginPath(test_case.ctx_filename, test_case.embed_mode);
201+
202+
Ort::SessionOptions session_options;
203+
std::unordered_map<std::string, std::string> ep_options;
204+
session_options.AppendExecutionProvider_V2(*ort_env, std::vector<Ort::ConstEpDevice>{plugin_ep_device}, ep_options);
205+
Ort::Session session(*ort_env, test_case.ctx_filename, session_options);
206+
RunModelWithSession(session);
207+
}
208+
}
209+
210+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_cpu_epctx_plugin_roundtrip_variants_absolute) {
211+
auto plugin_ep_device = GetOvCpuEpDevice();
212+
ASSERT_NE(plugin_ep_device, nullptr);
213+
214+
for (const auto& test_case : ep_context_cases) {
215+
if (test_case.embed_mode) {
216+
// TODO(ericcraw) Re-enable.
217+
// Skip the embed mode until upstream fix.
218+
continue;
219+
}
220+
221+
auto absolute_path = std::filesystem::absolute(test_case.ctx_filename).native();
222+
GenerateEpContextOnPluginPath(absolute_path.c_str(), test_case.embed_mode);
223+
224+
Ort::SessionOptions session_options;
225+
std::unordered_map<std::string, std::string> ep_options;
226+
session_options.AppendExecutionProvider_V2(*ort_env, std::vector<Ort::ConstEpDevice>{plugin_ep_device}, ep_options);
227+
Ort::Session session(*ort_env, absolute_path.c_str(), session_options);
228+
RunModelWithSession(session);
229+
}
230+
}
231+
232+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_multiple_devices) {
233+
auto plugin_ep_device = GetOvCpuEpDevice();
234+
ASSERT_NE(plugin_ep_device, nullptr);
235+
236+
std::vector<Ort::ConstEpDevice> multi_device_list(2, plugin_ep_device); // 2 copies of cpu device.
237+
238+
Ort::SessionOptions session_options;
239+
session_options.AppendExecutionProvider_V2(*ort_env, multi_device_list, std::unordered_map<std::string, std::string>{});
240+
Ort::Session session(*ort_env, ORT_TSTR("testdata/mul_1.onnx"), session_options);
241+
}
242+
243+
TEST_F(OrtEpLibraryOv, PluginEp_AppendV2_mixed_factory_devices_throw_exception) {
244+
auto ep_devices = ort_env->GetEpDevices();
245+
std::vector<Ort::ConstEpDevice> matching_devices;
246+
247+
for (const auto& device : ep_devices) {
248+
std::string ep_name = device.EpName();
249+
if (ep_name.find(registration_name) != std::string::npos &&
250+
(ep_name == registration_name || ep_name == registration_name + ".AUTO")) {
251+
matching_devices.push_back(device);
252+
}
253+
}
254+
255+
ASSERT_GT(matching_devices.size(), 1) << "Expected more than one matching EP device";
256+
257+
EXPECT_THROW({
258+
Ort::SessionOptions session_options;
259+
session_options.AppendExecutionProvider_V2(*ort_env, matching_devices, std::unordered_map<std::string, std::string>{});
260+
Ort::Session session(*ort_env, ORT_TSTR("testdata/mul_1.onnx"), session_options); }, Ort::Exception);
261+
}

0 commit comments

Comments
 (0)