From fd59da5dba2e93337119f188fab0a43d55be8dc5 Mon Sep 17 00:00:00 2001 From: Prakash Date: Wed, 17 Apr 2024 17:42:08 +0530 Subject: [PATCH] [OV JS] Expose Model.setFriendlyName and Model.getFriendlyName methods to Node.js api (#23743) This fixes #23566 Implemented Model.setFriendlyName and Model.getFriendlyName in Node.js api - Added Parameter Validation - Added Tests in model.test.js --------- Co-authored-by: Vishniakov Nikolai --- src/bindings/js/node/include/model_wrap.hpp | 17 +++++ src/bindings/js/node/lib/addon.ts | 2 + src/bindings/js/node/src/model_wrap.cpp | 26 +++++++ src/bindings/js/node/tests/model.test.js | 78 +++++++++++++++++++-- 4 files changed, 117 insertions(+), 6 deletions(-) diff --git a/src/bindings/js/node/include/model_wrap.hpp b/src/bindings/js/node/include/model_wrap.hpp index f23cb722202d1f..1e3373b6185095 100644 --- a/src/bindings/js/node/include/model_wrap.hpp +++ b/src/bindings/js/node/include/model_wrap.hpp @@ -84,6 +84,23 @@ class ModelWrap : public Napi::ObjectWrap { */ Napi::Value is_dynamic(const Napi::CallbackInfo& info); + /** + * @brief Sets a friendly name for a model. + * @param info Contains information about the environment and passed arguments + * this method accepts only one argument of type String, + * throws Napi::Undefined if more than 1 arguments are provided or the provided argument is not of type String + * @return Napi::Undefined + */ + Napi::Value set_friendly_name(const Napi::CallbackInfo& info); + + /** + * @brief Gets the friendly name for a model, if not set, gets the unique name + * @param info Contains information about the environment and passed arguments + * this method does not accept any arguments. If arguments are provided it throws ov::Exception. + * @return Napi::String containing friendly name + */ + Napi::Value get_friendly_name(const Napi::CallbackInfo& info); + private: std::shared_ptr _model; ov::Core _core; diff --git a/src/bindings/js/node/lib/addon.ts b/src/bindings/js/node/lib/addon.ts index 1909a15042e8da..030ea914e6c35e 100644 --- a/src/bindings/js/node/lib/addon.ts +++ b/src/bindings/js/node/lib/addon.ts @@ -67,6 +67,8 @@ interface Model { input(nameOrId?: string | number): Output; getName(): string; isDynamic(): boolean; + setFriendlyName(name: string): void; + getFriendlyName(): string; } interface CompiledModel { diff --git a/src/bindings/js/node/src/model_wrap.cpp b/src/bindings/js/node/src/model_wrap.cpp index a6effd6826e7fe..d22dd6701ab156 100644 --- a/src/bindings/js/node/src/model_wrap.cpp +++ b/src/bindings/js/node/src/model_wrap.cpp @@ -20,6 +20,8 @@ Napi::Function ModelWrap::get_class(Napi::Env env) { InstanceMethod("output", &ModelWrap::get_output), InstanceMethod("input", &ModelWrap::get_input), InstanceMethod("isDynamic", &ModelWrap::is_dynamic), + InstanceMethod("setFriendlyName", &ModelWrap::set_friendly_name), + InstanceMethod("getFriendlyName", &ModelWrap::get_friendly_name), InstanceAccessor<&ModelWrap::get_inputs>("inputs"), InstanceAccessor<&ModelWrap::get_outputs>("outputs")}); } @@ -128,3 +130,27 @@ Napi::Value ModelWrap::is_dynamic(const Napi::CallbackInfo& info) { const auto result = _model->is_dynamic(); return Napi::Boolean::New(env, result); } + +Napi::Value ModelWrap::set_friendly_name(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + try { + if (info.Length() != 1 || !info[0].IsString()) { + OPENVINO_THROW("Expected a single string argument for the friendly name"); + } + const auto name = info[0].As().Utf8Value(); + _model->set_friendly_name(name); + } catch (const std::exception& e) { + reportError(env, e.what()); + } + return env.Undefined(); +} + +Napi::Value ModelWrap::get_friendly_name(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + if (info.Length() > 0) { + reportError(env, "getFriendlyName() does not take any arguments"); + return env.Undefined(); + } + const auto friendly_name = _model->get_friendly_name(); + return Napi::String::New(env, friendly_name); +} diff --git a/src/bindings/js/node/tests/model.test.js b/src/bindings/js/node/tests/model.test.js index eec9372517e263..c157c003e18f6f 100644 --- a/src/bindings/js/node/tests/model.test.js +++ b/src/bindings/js/node/tests/model.test.js @@ -11,20 +11,86 @@ const core = new ov.Core(); const model = core.readModelSync(testXml); describe('Node.js Model.isDynamic()', () => { - it('should return a boolean value indicating if the model is dynamic', () => { const result = model.isDynamic(); - assert.strictEqual(typeof result, 'boolean', 'isDynamic() should return a boolean value'); + assert.strictEqual( + typeof result, + 'boolean', + 'isDynamic() should return a boolean value' + ); }); it('should not accept any arguments', () => { - assert.throws(() => { - model.isDynamic('unexpected argument'); - }, /^Error: isDynamic\(\) does not accept any arguments\.$/, 'Expected isDynamic to throw an error when called with arguments'); + assert.throws( + () => { + model.isDynamic('unexpected argument'); + }, + /^Error: isDynamic\(\) does not accept any arguments\.$/, + 'Expected isDynamic to throw an error when called with arguments' + ); }); it('returns false for a static model', () => { const expectedStatus = false; - assert.strictEqual(model.isDynamic(), expectedStatus, 'Expected isDynamic to return false for a static model'); + assert.strictEqual( + model.isDynamic(), + expectedStatus, + 'Expected isDynamic to return false for a static model' + ); + }); +}); + +describe('Node.js getFriendlyName() / setFriendlyName()', () => { + describe('getFriendlyName()', () => { + it('returns the unique name of the model if no friendly name is set', () => { + const expectedName = 'test_model'; + assert.strictEqual(model.getFriendlyName(), expectedName); + }); + it('throws an error when called with arguments', () => { + assert.throws( + () => model.getFriendlyName('unexpected argument'), + /getFriendlyName\(\) does not take any arguments/ + ); + }); + }); + describe('setFriendlyName()', () => { + it('sets a friendly name for the model', () => { + assert.doesNotThrow(() => model.setFriendlyName('MyFriendlyName')); + }); + + it('throws an error when called without a string argument', () => { + assert.throws( + () => model.setFriendlyName(), + /Expected a single string argument for the friendly name/ + ); + assert.throws( + () => model.setFriendlyName(123), + /Expected a single string argument for the friendly name/ + ); + }); + + it('throws an error when called with multiple arguments', () => { + assert.throws( + () => model.setFriendlyName('Name1', 'Name2'), + /Expected a single string argument for the friendly name/ + ); + }); + + it('returns the set friendly name of the model', () => { + const friendlyName = 'MyFriendlyModel'; + model.setFriendlyName(friendlyName); + assert.strictEqual(model.getFriendlyName(), friendlyName); + }); + + it('retains the last set friendly name when set multiple times', () => { + model.setFriendlyName('InitialName'); + model.setFriendlyName('FinalName'); + assert.strictEqual(model.getFriendlyName(), 'FinalName'); + }); + + it('handles setting an empty string as a friendly name', () => { + assert.doesNotThrow(() => model.setFriendlyName('')); + assert.strictEqual(model.getFriendlyName(), 'Model1'); + }); }); });