From 60a566b19d7e06372acd69901d949bbd6756ec1c Mon Sep 17 00:00:00 2001 From: hub-bla Date: Tue, 30 Jul 2024 19:04:46 +0200 Subject: [PATCH 1/6] expose set_property() and get_property() methods --- .../js/node/include/compiled_model.hpp | 16 +++++++++ src/bindings/js/node/src/compiled_model.cpp | 35 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/bindings/js/node/include/compiled_model.hpp b/src/bindings/js/node/include/compiled_model.hpp index 4e3834a3a527bd..56c483064be9ec 100644 --- a/src/bindings/js/node/include/compiled_model.hpp +++ b/src/bindings/js/node/include/compiled_model.hpp @@ -71,6 +71,22 @@ class CompiledModelWrap : public Napi::ObjectWrap { /** @brief Exports the compiled model to bytes/output stream. */ Napi::Value export_model(const Napi::CallbackInfo& info); + /** + * @brief Sets properties for current compiled model. + * @param info Contains information about the environment and passed arguments, + * this method accepts only one argument of type object. + * @return Napi::Undefined + */ + Napi::Value set_property(const Napi::CallbackInfo& info); + + /** + * @brief Gets property for current compiled model. + * @param info Contains information about the environment and passed arguments, + * this method accepts only one argument of type string. + * @return A Napi::Value + */ + Napi::Value get_property(const Napi::CallbackInfo& info); + private: /** @brief Gets node of a compiled model specified in CallbackInfo. */ Napi::Value get_node(const Napi::CallbackInfo& info, diff --git a/src/bindings/js/node/src/compiled_model.cpp b/src/bindings/js/node/src/compiled_model.cpp index 495322dab15823..c4fbf18fab5e63 100644 --- a/src/bindings/js/node/src/compiled_model.cpp +++ b/src/bindings/js/node/src/compiled_model.cpp @@ -5,6 +5,7 @@ #include "node/include/addon.hpp" #include "node/include/errors.hpp" +#include "node/include/helper.hpp" #include "node/include/infer_request.hpp" #include "node/include/node_output.hpp" @@ -20,7 +21,9 @@ Napi::Function CompiledModelWrap::get_class(Napi::Env env) { InstanceAccessor<&CompiledModelWrap::get_inputs>("inputs"), InstanceMethod("output", &CompiledModelWrap::get_output), InstanceAccessor<&CompiledModelWrap::get_outputs>("outputs"), - InstanceMethod("exportModelSync", &CompiledModelWrap::export_model)}); + InstanceMethod("exportModelSync", &CompiledModelWrap::export_model), + InstanceMethod("setProperty", &CompiledModelWrap::set_property), + InstanceMethod("getProperty", &CompiledModelWrap::get_property)}); } Napi::Object CompiledModelWrap::wrap(Napi::Env env, ov::CompiledModel compiled_model) { @@ -122,3 +125,33 @@ Napi::Value CompiledModelWrap::export_model(const Napi::CallbackInfo& info) { const auto& exported = _stream.str(); return Napi::Buffer::Copy(info.Env(), exported.c_str(), exported.size()); } + +Napi::Value CompiledModelWrap::set_property(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + try{ + if (info.Length() != 1 || !info[0].IsObject()) { + OPENVINO_THROW("Expected a single object argument for setting properties"); + } + const auto properties = to_anyMap(env, info[0]); + _compiled_model.set_property(properties); + } catch (const std::exception& e) { + reportError(env, e.what()); + } + return env.Undefined(); +} + +Napi::Value CompiledModelWrap::get_property(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + try { + if (info.Length() != 1 || !info[0].IsString()) { + reportError(env, "Expected a single string argument to retrieve property value"); + return env.Undefined(); + } + const auto property_name = info[0].As().Utf8Value(); + const auto property = _compiled_model.get_property(property_name); + return any_to_js(info, property); + } catch (const std::exception& e) { + reportError(env, e.what()); + } + return env.Undefined(); +} From ac079226ae2ae2190241b0b16f04344bb95da1de Mon Sep 17 00:00:00 2001 From: hub-bla Date: Tue, 30 Jul 2024 19:05:36 +0200 Subject: [PATCH 2/6] update TypeScript definition --- src/bindings/js/node/lib/addon.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bindings/js/node/lib/addon.ts b/src/bindings/js/node/lib/addon.ts index b5909ea9f3ae03..4361d912923447 100644 --- a/src/bindings/js/node/lib/addon.ts +++ b/src/bindings/js/node/lib/addon.ts @@ -296,6 +296,12 @@ interface CompiledModel { inputs: Output[]; /** It gets all outputs of a compiled model. */ outputs: Output[]; + /** + * It gets property for current compiled model. + * @param propertyName A string to get property value. + * @returns property value. + */ + getProperty(propertyName: string): string | number | boolean; /** * It creates an inference request object used to infer the compiled model. * @return {InferRequest} @@ -344,7 +350,14 @@ interface CompiledModel { * @returns {Output} A compiled model input. */ input(name: string): Output; - + /** + * It sets properties for current compiled model. Properties + * can be retrieved via {@link CompiledModel.getProperty}. + * @param property The object to set properties for current compiled model. + */ + setProperty(property: { + [propertyName: string]: string | number | boolean + }): void; } /** From 6ac3e0404baaaaad51c19fe59e9cc8cd74787901 Mon Sep 17 00:00:00 2001 From: hub-bla Date: Tue, 30 Jul 2024 19:06:16 +0200 Subject: [PATCH 3/6] create unit tests for get_property and set_property methods of compiled model --- .../js/node/tests/unit/compiled_model.test.js | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/bindings/js/node/tests/unit/compiled_model.test.js diff --git a/src/bindings/js/node/tests/unit/compiled_model.test.js b/src/bindings/js/node/tests/unit/compiled_model.test.js new file mode 100644 index 00000000000000..2a2d205cb4318c --- /dev/null +++ b/src/bindings/js/node/tests/unit/compiled_model.test.js @@ -0,0 +1,78 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +const { addon: ov } = require('../..'); +const assert = require('assert'); +const { describe, it } = require('node:test'); +const { getModelPath } = require('./utils.js'); + +const testXml = getModelPath().xml; +const core = new ov.Core(); +const properties = { + "AUTO_BATCH_TIMEOUT": '1' +}; +const compiledModel = core.compileModelSync(testXml, 'BATCH:CPU', properties); + +describe('setProperty() / getProperty()', () => { + + describe('getProperty()', () => { + it('returns the value of property from compiled model', () => { + assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), '1'); + }); + it('throws an error when called without arguments', () => { + assert.throws( + () => compiledModel.getProperty(), + /Expected a single string argument to retrieve property value/ + ); + }); + it('throws an error when called with property name that does not exists', ()=>{ + assert.throws( + () => compiledModel.getProperty('PROPERTY_THAT_DOES_NOT_EXIST') + ); + }); + }); + + describe('setProperty()', () => { + it('sets a properties for compiled model', () => { + properties["AUTO_BATCH_TIMEOUT"] = '1000'; + assert.doesNotThrow(() => compiledModel.setProperty(properties)); + }); + + it('throws an error when called without an object argument', () => { + assert.throws( + () => compiledModel.setProperty(), + /Expected a single object argument for setting properties/ + ); + }); + it('throws an error when called with wrong argument', () => { + assert.throws( + () => compiledModel.setProperty(123), + /Expected a single object argument for setting properties/ + ); + }); + + it('throws an error when called with multiple arguments', () => { + assert.throws( + () => compiledModel.setProperty({"PERFORMANCE_HINT": "THROUGHPUT"}, {"NUM_STREAMS": "AUTO"}), + /Expected a single object argument for setting properties/ + ); + }); + + it('returns the set property of the compiled model', () => { + properties["AUTO_BATCH_TIMEOUT"] = '123'; + compiledModel.setProperty(properties); + assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), 123); + }); + + it('retains the last set property when set multiple times', () => { + compiledModel.setProperty({"AUTO_BATCH_TIMEOUT": '321'}); + compiledModel.setProperty({'AUTO_BATCH_TIMEOUT': '132'}); + assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), 132); + }); + + it('allows to pass empty object', () => { + assert.doesNotThrow(() => compiledModel.setProperty({})); + }); + }); +}); From a727f0f9bfe8a07a2eef222f9b1a640b66d339b2 Mon Sep 17 00:00:00 2001 From: hub-bla Date: Fri, 9 Aug 2024 12:58:29 +0200 Subject: [PATCH 4/6] update addon.ts --- src/bindings/js/node/lib/addon.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bindings/js/node/lib/addon.ts b/src/bindings/js/node/lib/addon.ts index 3ef8b9589ac5bc..a48ac06f9574de 100644 --- a/src/bindings/js/node/lib/addon.ts +++ b/src/bindings/js/node/lib/addon.ts @@ -302,9 +302,9 @@ interface CompiledModel { /** It gets all outputs of a compiled model. */ outputs: Output[]; /** - * It gets property for current compiled model. - * @param propertyName A string to get property value. - * @returns property value. + * It gets the property for the current compiled model. + * @param propertyName A string to get the property value. + * @returns The property value. */ getProperty(propertyName: string): string | number | boolean; /** @@ -356,11 +356,12 @@ interface CompiledModel { */ input(name: string): Output; /** - * It sets properties for current compiled model. Properties + * It sets properties for the current compiled model. Properties * can be retrieved via {@link CompiledModel.getProperty}. - * @param property The object to set properties for current compiled model. + * @param property An object with the key-value pairs. + * (property name, property value) */ - setProperty(property: { + setProperty(properties: { [propertyName: string]: string | number | boolean }): void; } From cf7c7efdbdc04ad9bbb828de4afc9cbd470703e2 Mon Sep 17 00:00:00 2001 From: hub-bla Date: Fri, 9 Aug 2024 14:25:55 +0200 Subject: [PATCH 5/6] use ov::js::validate --- src/bindings/js/node/src/compiled_model.cpp | 32 ++++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/bindings/js/node/src/compiled_model.cpp b/src/bindings/js/node/src/compiled_model.cpp index c4fbf18fab5e63..f9d13ddeb66d13 100644 --- a/src/bindings/js/node/src/compiled_model.cpp +++ b/src/bindings/js/node/src/compiled_model.cpp @@ -8,6 +8,7 @@ #include "node/include/helper.hpp" #include "node/include/infer_request.hpp" #include "node/include/node_output.hpp" +#include "node/include/type_validation.hpp" CompiledModelWrap::CompiledModelWrap(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info), @@ -126,30 +127,33 @@ Napi::Value CompiledModelWrap::export_model(const Napi::CallbackInfo& info) { return Napi::Buffer::Copy(info.Env(), exported.c_str(), exported.size()); } -Napi::Value CompiledModelWrap::set_property(const Napi::CallbackInfo &info) { +Napi::Value CompiledModelWrap::set_property(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - try{ - if (info.Length() != 1 || !info[0].IsObject()) { - OPENVINO_THROW("Expected a single object argument for setting properties"); + std::vector allowed_signatures; + try { + if (ov::js::validate(info, allowed_signatures)) { + const auto properties = to_anyMap(env, info[0]); + _compiled_model.set_property(properties); + } else { + OPENVINO_THROW("'setProperty'", ov::js::get_parameters_error_msg(info, allowed_signatures)); } - const auto properties = to_anyMap(env, info[0]); - _compiled_model.set_property(properties); } catch (const std::exception& e) { - reportError(env, e.what()); + reportError(env, e.what()); } return env.Undefined(); } -Napi::Value CompiledModelWrap::get_property(const Napi::CallbackInfo &info) { +Napi::Value CompiledModelWrap::get_property(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); + std::vector allowed_signatures; try { - if (info.Length() != 1 || !info[0].IsString()) { - reportError(env, "Expected a single string argument to retrieve property value"); - return env.Undefined(); + if (ov::js::validate(info, allowed_signatures)) { + const auto property_name = info[0].As().Utf8Value(); + const auto property = _compiled_model.get_property(property_name); + return any_to_js(info, property); + } else { + OPENVINO_THROW("'getProperty'", ov::js::get_parameters_error_msg(info, allowed_signatures)); } - const auto property_name = info[0].As().Utf8Value(); - const auto property = _compiled_model.get_property(property_name); - return any_to_js(info, property); } catch (const std::exception& e) { reportError(env, e.what()); } From 819d07a5abe9a2658b753baea89b442f0dbc1a7e Mon Sep 17 00:00:00 2001 From: hub-bla Date: Fri, 9 Aug 2024 14:26:23 +0200 Subject: [PATCH 6/6] update test messages --- src/bindings/js/node/tests/unit/compiled_model.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bindings/js/node/tests/unit/compiled_model.test.js b/src/bindings/js/node/tests/unit/compiled_model.test.js index 2a2d205cb4318c..6b33296131b04d 100644 --- a/src/bindings/js/node/tests/unit/compiled_model.test.js +++ b/src/bindings/js/node/tests/unit/compiled_model.test.js @@ -23,7 +23,7 @@ describe('setProperty() / getProperty()', () => { it('throws an error when called without arguments', () => { assert.throws( () => compiledModel.getProperty(), - /Expected a single string argument to retrieve property value/ + /'getProperty' method called with incorrect parameters/ ); }); it('throws an error when called with property name that does not exists', ()=>{ @@ -42,20 +42,20 @@ describe('setProperty() / getProperty()', () => { it('throws an error when called without an object argument', () => { assert.throws( () => compiledModel.setProperty(), - /Expected a single object argument for setting properties/ + /'setProperty' method called with incorrect parameters/ ); }); it('throws an error when called with wrong argument', () => { assert.throws( () => compiledModel.setProperty(123), - /Expected a single object argument for setting properties/ + /'setProperty' method called with incorrect parameters/ ); }); it('throws an error when called with multiple arguments', () => { assert.throws( () => compiledModel.setProperty({"PERFORMANCE_HINT": "THROUGHPUT"}, {"NUM_STREAMS": "AUTO"}), - /Expected a single object argument for setting properties/ + /'setProperty' method called with incorrect parameters/ ); });