From 8d38f89454d741d28005b0d6cbcdd16abac8f86f Mon Sep 17 00:00:00 2001 From: JckXia Date: Fri, 6 Jan 2023 11:51:43 -0500 Subject: [PATCH 1/7] test: refactor part of objectRef set tests --- test/object_reference.cc | 147 ++++++++++++++++++++++++++++++++++++++- test/object_reference.js | 33 +++++++-- 2 files changed, 171 insertions(+), 9 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index 34f952088..5825feecf 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -3,6 +3,7 @@ are not Objects by creating a blank Object and setting Values to it. Subclasses of Objects can only be set using an ObjectReference by first casting it as an Object. */ +#include #include "napi.h" #include "test_helper.h" @@ -16,6 +17,145 @@ ObjectReference casted_weak; ObjectReference casted_persistent; ObjectReference casted_reference; +// Set keys can be one of: +// C style string OR Napi::Value, which we cast to std::string& utf8 + +// Set values can be one of: +// Napi::Value +// napi_value (req static_cast) +// const char* (c style string) +// boolean +// double + +enum VAL_TYPES { JS = 0, C_STR, BOOL, INT, DOUBLE, JS_CAST }; + +void SetObjectWithCStringKey(Napi::ObjectReference& obj, + Napi::Value key, + Napi::Value val, + int valType) { + std::string c_key = key.As().Utf8Value(); + switch (valType) { + case JS: + obj.Set(c_key.c_str(), val); + break; + + case JS_CAST: + obj.Set(c_key.c_str(), static_cast(val)); + break; + + case C_STR: + obj.Set(c_key.c_str(), val.As().Utf8Value().c_str()); + break; + + case BOOL: + obj.Set(c_key.c_str(), val.As().Value()); + break; + + case DOUBLE: + obj.Set(c_key.c_str(), val.As().DoubleValue()); + break; + } +} + +void SetObjectWithJsStringKey(Napi::ObjectReference& obj, + Napi::Value key, + Napi::Value val, + int valType) { + auto c_key = key.As(); + switch (valType) { + case JS: + obj.Set(c_key, val); + break; + + case JS_CAST: + obj.Set(c_key, static_cast(val)); + break; + + case C_STR: + obj.Set(c_key, val.As().Utf8Value().c_str()); + break; + + case BOOL: + obj.Set(c_key, val.As().Value()); + break; + + case DOUBLE: + obj.Set(c_key, val.As().DoubleValue()); + break; + } +} + +void SetObjectWithIntKey(Napi::ObjectReference& obj, + Napi::Value key, + Napi::Value val, + int valType) { + auto c_key = key.As().Uint32Value(); + switch (valType) { + case JS: + obj.Set(c_key, val); + break; + + case JS_CAST: + obj.Set(c_key, static_cast(val)); + break; + + case C_STR: + obj.Set(c_key, val.As().Utf8Value().c_str()); + break; + + case BOOL: + obj.Set(c_key, val.As().Value()); + break; + + case DOUBLE: + obj.Set(c_key, val.As().DoubleValue()); + break; + } +} + +void SetObject(const Napi::CallbackInfo& info) { + Env env = info.Env(); + HandleScope scope(env); + + weak = Weak(Object::New(env)); + weak.SuppressDestruct(); + + persistent = Persistent(Object::New(env)); + persistent.SuppressDestruct(); + + reference = Reference::New(Object::New(env), 2); + reference.SuppressDestruct(); + + Napi::Object configObject = info[0].As(); + + int keyType = configObject.Get("keyType").As().Uint32Value(); + int valType = configObject.Get("valType").As().Uint32Value(); + Napi::Value key = configObject.Get("key"); + Napi::Value val = configObject.Get("val"); + + switch (keyType) { + case JS: + SetObjectWithJsStringKey(weak, key, val, valType); + SetObjectWithJsStringKey(persistent, key, val, valType); + SetObjectWithJsStringKey(reference, key, val, valType); + break; + + case C_STR: + SetObjectWithCStringKey(weak, key, val, valType); + SetObjectWithCStringKey(persistent, key, val, valType); + SetObjectWithCStringKey(reference, key, val, valType); + break; + + case INT: + SetObjectWithIntKey(weak, key, val, valType); + SetObjectWithIntKey(persistent, key, val, valType); + SetObjectWithIntKey(reference, key, val, valType); + + default: + break; + } +} + // info[0] is the key, which can be either a string or a number. // info[1] is the value. // info[2] is a flag that differentiates whether the key is a @@ -39,9 +179,9 @@ void SetObjects(const CallbackInfo& info) { persistent.Set(info[0].As(), info[1]); reference.Set(info[0].As(), info[1]); } else { - weak.Set(info[0].As().Utf8Value(), info[1]); - persistent.Set(info[0].As().Utf8Value(), info[1]); - reference.Set(info[0].As().Utf8Value(), info[1]); + weak.Set(info[0].As().Utf8Value().c_str(), info[1]); + persistent.Set(info[0].As().Utf8Value().c_str(), info[1]); + reference.Set(info[0].As().Utf8Value().c_str(), info[1]); } } else if (info[0].IsNumber()) { weak.Set(info[0].As(), info[1]); @@ -207,6 +347,7 @@ Object InitObjectReference(Env env) { Object exports = Object::New(env); exports["setCastedObjects"] = Function::New(env, SetCastedObjects); + exports["setObject"] = Function::New(env, SetObject); exports["setObjects"] = Function::New(env, SetObjects); exports["getCastedFromValue"] = Function::New(env, GetCastedFromValue); exports["getFromGetter"] = Function::New(env, GetFromGetter); diff --git a/test/object_reference.js b/test/object_reference.js index c1e730813..c67e88153 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -16,6 +16,15 @@ const testUtil = require('./testUtil'); module.exports = require('./common').runTest(test); +const enumType = { + JS: 0, + C_STR: 1, + BOOL: 2, + INT: 3, + DOUBLE: 4, + JS_CAST: 5 +}; + function test (binding) { function testCastedEqual (testToCompare) { const compareTest = ['hello', 'world', '!']; @@ -74,13 +83,25 @@ function test (binding) { 'Weak', () => { - binding.objectreference.setObjects('hello', 'world'); - const test = binding.objectreference.getFromValue('weak'); - const test2 = binding.objectreference.getFromGetter('weak', 'hello'); + const configObjects = [ + { keyType: enumType.C_STR, valType: enumType.JS, key: 'hello', val: 'world' }, + { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'world' }, + { keyType: enumType.C_STR, valType: enumType.BOOL, key: 'hello', val: false }, + { keyType: enumType.C_STR, valType: enumType.DOUBLE, key: 'hello', val: 3.56 }, + { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' } + ]; - assert.deepEqual({ hello: 'world' }, test); - assert.equal('world', test2); - assert.equal(test.hello, test2); + for (const configObject of configObjects) { + binding.objectreference.setObject(configObject); + const test = binding.objectreference.getFromValue('weak'); + const test2 = binding.objectreference.getFromGetter('weak', configObject.key); + + const assertObject = { + [configObject.key]: configObject.val + }; + assert.deepEqual(assertObject, test); + assert.equal(configObject.val, test2); + } }, () => { binding.objectreference.setObjects('hello', 'world', 'javascript'); From 950e9da95f0c003daf039fe62a41325574f32a99 Mon Sep 17 00:00:00 2001 From: JckXia Date: Fri, 6 Jan 2023 13:57:32 -0500 Subject: [PATCH 2/7] test: Refactor weak ref object tests --- test/object_reference.cc | 8 ++------ test/object_reference.js | 37 +++++++++++++------------------------ 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index 5825feecf..d4fd28d26 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -61,7 +61,7 @@ void SetObjectWithJsStringKey(Napi::ObjectReference& obj, Napi::Value key, Napi::Value val, int valType) { - auto c_key = key.As(); + std::string c_key = key.As(); switch (valType) { case JS: obj.Set(c_key, val); @@ -71,10 +71,6 @@ void SetObjectWithJsStringKey(Napi::ObjectReference& obj, obj.Set(c_key, static_cast(val)); break; - case C_STR: - obj.Set(c_key, val.As().Utf8Value().c_str()); - break; - case BOOL: obj.Set(c_key, val.As().Value()); break; @@ -89,7 +85,7 @@ void SetObjectWithIntKey(Napi::ObjectReference& obj, Napi::Value key, Napi::Value val, int valType) { - auto c_key = key.As().Uint32Value(); + uint32_t c_key = key.As().Uint32Value(); switch (valType) { case JS: obj.Set(c_key, val); diff --git a/test/object_reference.js b/test/object_reference.js index c67e88153..4ce52c296 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -88,7 +88,15 @@ function test (binding) { { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'world' }, { keyType: enumType.C_STR, valType: enumType.BOOL, key: 'hello', val: false }, { keyType: enumType.C_STR, valType: enumType.DOUBLE, key: 'hello', val: 3.56 }, - { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' } + { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' }, + { keyType: enumType.JS, valType: enumType.JS, key: 'hello_js', val: 'world_js' }, + { keyType: enumType.JS, valType: enumType.JS_CAST, key: 'hello_js', val: 'world_js' }, + { keyType: enumType.JS, valType: enumType.BOOL, key: 'hello_js', val: true }, + { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.JS_CAST, key: 2, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.C_STR, key: 3, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.BOOL, key: 3, val: false }, + { keyType: enumType.INT, valType: enumType.DOUBLE, key: 4, val: 3.14159 } ]; for (const configObject of configObjects) { @@ -102,38 +110,19 @@ function test (binding) { assert.deepEqual(assertObject, test); assert.equal(configObject.val, test2); } - }, - () => { - binding.objectreference.setObjects('hello', 'world', 'javascript'); - const test = binding.objectreference.getFromValue('weak'); - const test2 = binding.objectreference.getFromValue('weak', 'hello'); - - assert.deepEqual({ hello: 'world' }, test); - assert.deepEqual({ hello: 'world' }, test2); - assert.equal(test, test2); - }, - () => { - binding.objectreference.setObjects(1, 'hello world'); - const test = binding.objectreference.getFromValue('weak'); - const test2 = binding.objectreference.getFromGetter('weak', 1); + }, () => { + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); - assert.deepEqual({ 1: 'hello world' }, test); - assert.equal('hello world', test2); - assert.equal(test[1], test2); - }, - () => { - binding.objectreference.setObjects(0, 'hello'); - binding.objectreference.setObjects(1, 'world'); const test = binding.objectreference.getFromValue('weak'); const test2 = binding.objectreference.getFromGetter('weak', 0); const test3 = binding.objectreference.getFromGetter('weak', 1); - assert.deepEqual({ 1: 'world' }, test); assert.equal(undefined, test2); assert.equal('world', test3); }, () => { - binding.objectreference.setObjects('hello', 'world'); + binding.objectreference.setObject({ keyType: enumType.JS, valType: enumType.JS, key: 'hello', val: 'world' }); assert.doesNotThrow( () => { let rcount = binding.objectreference.refObjects('weak'); From 49189323b9d7f9b49ac8ba5f4b74ef7f889a1c1b Mon Sep 17 00:00:00 2001 From: JckXia Date: Fri, 6 Jan 2023 15:06:50 -0500 Subject: [PATCH 3/7] test: Add CPP_STR type, using MaybeUnWrap to work with Maybes --- test/object_reference.cc | 39 +++++++++++++++++++++++++++++---------- test/object_reference.js | 26 +++++++++++++++----------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index d4fd28d26..42696bde2 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -27,7 +27,7 @@ ObjectReference casted_reference; // boolean // double -enum VAL_TYPES { JS = 0, C_STR, BOOL, INT, DOUBLE, JS_CAST }; +enum VAL_TYPES { JS = 0, C_STR, CPP_STR, BOOL, INT, DOUBLE, JS_CAST }; void SetObjectWithCStringKey(Napi::ObjectReference& obj, Napi::Value key, @@ -43,9 +43,11 @@ void SetObjectWithCStringKey(Napi::ObjectReference& obj, obj.Set(c_key.c_str(), static_cast(val)); break; - case C_STR: - obj.Set(c_key.c_str(), val.As().Utf8Value().c_str()); + case C_STR: { + std::string c_val = val.As().Utf8Value(); + obj.Set(c_key.c_str(), c_val.c_str()); break; + } case BOOL: obj.Set(c_key.c_str(), val.As().Value()); @@ -57,6 +59,7 @@ void SetObjectWithCStringKey(Napi::ObjectReference& obj, } } +// TODO: Change this function name to SetObjectWithCppStringKey void SetObjectWithJsStringKey(Napi::ObjectReference& obj, Napi::Value key, Napi::Value val, @@ -71,6 +74,12 @@ void SetObjectWithJsStringKey(Napi::ObjectReference& obj, obj.Set(c_key, static_cast(val)); break; + case CPP_STR: { + std::string c_val = val.As(); + obj.Set(c_key, c_val); + break; + } + case BOOL: obj.Set(c_key, val.As().Value()); break; @@ -95,9 +104,17 @@ void SetObjectWithIntKey(Napi::ObjectReference& obj, obj.Set(c_key, static_cast(val)); break; - case C_STR: - obj.Set(c_key, val.As().Utf8Value().c_str()); + case C_STR: { + std::string c_val = val.As(); + obj.Set(c_key, c_val.c_str()); break; + } + + case CPP_STR: { + std::string cpp_val = val.As(); + obj.Set(c_key, cpp_val); + break; + } case BOOL: obj.Set(c_key, val.As().Value()); @@ -124,13 +141,15 @@ void SetObject(const Napi::CallbackInfo& info) { Napi::Object configObject = info[0].As(); - int keyType = configObject.Get("keyType").As().Uint32Value(); - int valType = configObject.Get("valType").As().Uint32Value(); - Napi::Value key = configObject.Get("key"); - Napi::Value val = configObject.Get("val"); + int keyType = + MaybeUnwrap(configObject.Get("keyType")).As().Uint32Value(); + int valType = + MaybeUnwrap(configObject.Get("valType")).As().Uint32Value(); + Napi::Value key = MaybeUnwrap(configObject.Get("key")); + Napi::Value val = MaybeUnwrap(configObject.Get("val")); switch (keyType) { - case JS: + case CPP_STR: SetObjectWithJsStringKey(weak, key, val, valType); SetObjectWithJsStringKey(persistent, key, val, valType); SetObjectWithJsStringKey(reference, key, val, valType); diff --git a/test/object_reference.js b/test/object_reference.js index 4ce52c296..e07734979 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -17,12 +17,13 @@ const testUtil = require('./testUtil'); module.exports = require('./common').runTest(test); const enumType = { - JS: 0, - C_STR: 1, - BOOL: 2, - INT: 3, - DOUBLE: 4, - JS_CAST: 5 + JS: 0, // Napi::Value + C_STR: 1, // const char * + CPP_STR: 2, // std::string + BOOL: 3, // bool + INT: 4, // uint32_t + DOUBLE: 5, // double + JS_CAST: 6 // napi_value }; function test (binding) { @@ -84,17 +85,20 @@ function test (binding) { 'Weak', () => { const configObjects = [ - { keyType: enumType.C_STR, valType: enumType.JS, key: 'hello', val: 'world' }, - { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'world' }, + { keyType: enumType.C_STR, valType: enumType.JS, key: 'hello', val: 'worlds' }, + { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'worldd' }, { keyType: enumType.C_STR, valType: enumType.BOOL, key: 'hello', val: false }, { keyType: enumType.C_STR, valType: enumType.DOUBLE, key: 'hello', val: 3.56 }, { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' }, - { keyType: enumType.JS, valType: enumType.JS, key: 'hello_js', val: 'world_js' }, - { keyType: enumType.JS, valType: enumType.JS_CAST, key: 'hello_js', val: 'world_js' }, - { keyType: enumType.JS, valType: enumType.BOOL, key: 'hello_js', val: true }, + { keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello_cpp', val: 'world_js' }, + { keyType: enumType.CPP_STR, valType: enumType.JS_CAST, key: 'hello_cpp', val: 'world_js_cast' }, + { keyType: enumType.CPP_STR, valType: enumType.CPP_STR, key: 'hello_cpp', val: 'world_cpp_str' }, + { keyType: enumType.CPP_STR, valType: enumType.BOOL, key: 'hello_cpp', val: true }, + { keyType: enumType.CPP_STR, valType: enumType.DOUBLE, key: 'hello_cpp', val: 3.58 }, { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'hello world' }, { keyType: enumType.INT, valType: enumType.JS_CAST, key: 2, val: 'hello world' }, { keyType: enumType.INT, valType: enumType.C_STR, key: 3, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.CPP_STR, key: 8, val: 'hello world' }, { keyType: enumType.INT, valType: enumType.BOOL, key: 3, val: false }, { keyType: enumType.INT, valType: enumType.DOUBLE, key: 4, val: 3.14159 } ]; From ac4d0064e838afbb7bb6c054c379535f2d24ed55 Mon Sep 17 00:00:00 2001 From: JckXia Date: Fri, 6 Jan 2023 16:44:44 -0500 Subject: [PATCH 4/7] test: Complete test coverage for ObjectRef::Set --- test/object_reference.js | 110 ++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 64 deletions(-) diff --git a/test/object_reference.js b/test/object_reference.js index e07734979..621ba625c 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -26,6 +26,25 @@ const enumType = { JS_CAST: 6 // napi_value }; +const configObjects = [ + { keyType: enumType.C_STR, valType: enumType.JS, key: 'hello', val: 'worlds' }, + { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'worldd' }, + { keyType: enumType.C_STR, valType: enumType.BOOL, key: 'hello', val: false }, + { keyType: enumType.C_STR, valType: enumType.DOUBLE, key: 'hello', val: 3.56 }, + { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' }, + { keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello_cpp', val: 'world_js' }, + { keyType: enumType.CPP_STR, valType: enumType.JS_CAST, key: 'hello_cpp', val: 'world_js_cast' }, + { keyType: enumType.CPP_STR, valType: enumType.CPP_STR, key: 'hello_cpp', val: 'world_cpp_str' }, + { keyType: enumType.CPP_STR, valType: enumType.BOOL, key: 'hello_cpp', val: true }, + { keyType: enumType.CPP_STR, valType: enumType.DOUBLE, key: 'hello_cpp', val: 3.58 }, + { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.JS_CAST, key: 2, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.C_STR, key: 3, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.CPP_STR, key: 8, val: 'hello world' }, + { keyType: enumType.INT, valType: enumType.BOOL, key: 3, val: false }, + { keyType: enumType.INT, valType: enumType.DOUBLE, key: 4, val: 3.14159 } +]; + function test (binding) { function testCastedEqual (testToCompare) { const compareTest = ['hello', 'world', '!']; @@ -84,25 +103,6 @@ function test (binding) { 'Weak', () => { - const configObjects = [ - { keyType: enumType.C_STR, valType: enumType.JS, key: 'hello', val: 'worlds' }, - { keyType: enumType.C_STR, valType: enumType.C_STR, key: 'hello', val: 'worldd' }, - { keyType: enumType.C_STR, valType: enumType.BOOL, key: 'hello', val: false }, - { keyType: enumType.C_STR, valType: enumType.DOUBLE, key: 'hello', val: 3.56 }, - { keyType: enumType.C_STR, valType: enumType.JS_CAST, key: 'hello_cast', val: 'world' }, - { keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello_cpp', val: 'world_js' }, - { keyType: enumType.CPP_STR, valType: enumType.JS_CAST, key: 'hello_cpp', val: 'world_js_cast' }, - { keyType: enumType.CPP_STR, valType: enumType.CPP_STR, key: 'hello_cpp', val: 'world_cpp_str' }, - { keyType: enumType.CPP_STR, valType: enumType.BOOL, key: 'hello_cpp', val: true }, - { keyType: enumType.CPP_STR, valType: enumType.DOUBLE, key: 'hello_cpp', val: 3.58 }, - { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'hello world' }, - { keyType: enumType.INT, valType: enumType.JS_CAST, key: 2, val: 'hello world' }, - { keyType: enumType.INT, valType: enumType.C_STR, key: 3, val: 'hello world' }, - { keyType: enumType.INT, valType: enumType.CPP_STR, key: 8, val: 'hello world' }, - { keyType: enumType.INT, valType: enumType.BOOL, key: 3, val: false }, - { keyType: enumType.INT, valType: enumType.DOUBLE, key: 4, val: 3.14159 } - ]; - for (const configObject of configObjects) { binding.objectreference.setObject(configObject); const test = binding.objectreference.getFromValue('weak'); @@ -146,16 +146,20 @@ function test (binding) { 'Persistent', () => { - binding.objectreference.setObjects('hello', 'world'); - const test = binding.objectreference.getFromValue('persistent'); - const test2 = binding.objectreference.getFromGetter('persistent', 'hello'); + for (const configObject of configObjects) { + binding.objectreference.setObject(configObject); + const test = binding.objectreference.getFromValue('persistent'); + const test2 = binding.objectreference.getFromGetter('persistent', configObject.key); - assert.deepEqual({ hello: 'world' }, test); - assert.equal('world', test2); - assert.equal(test.hello, test2); + const assertObject = { + [configObject.key]: configObject.val + }; + assert.deepEqual(assertObject, test); + assert.equal(configObject.val, test2); + } }, () => { - binding.objectreference.setObjects('hello', 'world', 'javascript'); + binding.objectreference.setObject({ keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello', val: 'world' }); const test = binding.objectreference.getFromValue('persistent'); const test2 = binding.objectreference.getFromValue('persistent', 'hello'); @@ -164,17 +168,9 @@ function test (binding) { assert.deepEqual(test, test2); }, () => { - binding.objectreference.setObjects(1, 'hello world'); - const test = binding.objectreference.getFromValue('persistent'); - const test2 = binding.objectreference.getFromGetter('persistent', 1); + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); - assert.deepEqual({ 1: 'hello world' }, test); - assert.equal('hello world', test2); - assert.equal(test[1], test2); - }, - () => { - binding.objectreference.setObjects(0, 'hello'); - binding.objectreference.setObjects(1, 'world'); const test = binding.objectreference.getFromValue('persistent'); const test2 = binding.objectreference.getFromGetter('persistent', 0); const test3 = binding.objectreference.getFromGetter('persistent', 1); @@ -184,7 +180,7 @@ function test (binding) { assert.equal('world', test3); }, () => { - binding.objectreference.setObjects('hello', 'world'); + binding.objectreference.setObject({ keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello', val: 'world' }); assert.doesNotThrow( () => { let rcount = binding.objectreference.unrefObjects('persistent'); @@ -210,35 +206,21 @@ function test (binding) { 'References', () => { - binding.objectreference.setObjects('hello', 'world'); - const test = binding.objectreference.getFromValue(); - const test2 = binding.objectreference.getFromGetter('hello'); - - assert.deepEqual({ hello: 'world' }, test); - assert.equal('world', test2); - assert.equal(test.hello, test2); - }, - () => { - binding.objectreference.setObjects('hello', 'world', 'javascript'); - const test = binding.objectreference.getFromValue(); - const test2 = binding.objectreference.getFromValue('hello'); - - assert.deepEqual({ hello: 'world' }, test); - assert.deepEqual({ hello: 'world' }, test2); - assert.deepEqual(test, test2); - }, - () => { - binding.objectreference.setObjects(1, 'hello world'); - const test = binding.objectreference.getFromValue(); - const test2 = binding.objectreference.getFromGetter(1); + for (const configObject of configObjects) { + binding.objectreference.setObject(configObject); + const test = binding.objectreference.getFromValue(); + const test2 = binding.objectreference.getFromGetter(configObject.key); - assert.deepEqual({ 1: 'hello world' }, test); - assert.equal('hello world', test2); - assert.equal(test[1], test2); + const assertObject = { + [configObject.key]: configObject.val + }; + assert.deepEqual(assertObject, test); + assert.equal(configObject.val, test2); + } }, () => { - binding.objectreference.setObjects(0, 'hello'); - binding.objectreference.setObjects(1, 'world'); + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); + binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); const test = binding.objectreference.getFromValue(); const test2 = binding.objectreference.getFromGetter(0); const test3 = binding.objectreference.getFromGetter(1); @@ -248,7 +230,7 @@ function test (binding) { assert.equal('world', test3); }, () => { - binding.objectreference.setObjects('hello', 'world'); + binding.objectreference.setObject({ keyType: enumType.CPP_STR, valType: enumType.JS, key: 'hello', val: 'world' }); assert.doesNotThrow( () => { let rcount = binding.objectreference.unrefObjects('references'); From 8527e1a0903d8b53a01dabc2cd78c9620664ab5c Mon Sep 17 00:00:00 2001 From: JckXia Date: Sat, 7 Jan 2023 18:51:42 -0500 Subject: [PATCH 5/7] test: Refactor GET tests --- test/object_reference.cc | 85 +++++++++++++++++++++++----------------- test/object_reference.js | 40 +++++++++++-------- 2 files changed, 72 insertions(+), 53 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index 42696bde2..39d525b90 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -171,40 +171,6 @@ void SetObject(const Napi::CallbackInfo& info) { } } -// info[0] is the key, which can be either a string or a number. -// info[1] is the value. -// info[2] is a flag that differentiates whether the key is a -// C string or a JavaScript string. -void SetObjects(const CallbackInfo& info) { - Env env = info.Env(); - HandleScope scope(env); - - weak = Weak(Object::New(env)); - weak.SuppressDestruct(); - - persistent = Persistent(Object::New(env)); - persistent.SuppressDestruct(); - - reference = Reference::New(Object::New(env), 2); - reference.SuppressDestruct(); - - if (info[0].IsString()) { - if (info[2].As() == String::New(env, "javascript")) { - weak.Set(info[0].As(), info[1]); - persistent.Set(info[0].As(), info[1]); - reference.Set(info[0].As(), info[1]); - } else { - weak.Set(info[0].As().Utf8Value().c_str(), info[1]); - persistent.Set(info[0].As().Utf8Value().c_str(), info[1]); - reference.Set(info[0].As().Utf8Value().c_str(), info[1]); - } - } else if (info[0].IsNumber()) { - weak.Set(info[0].As(), info[1]); - persistent.Set(info[0].As(), info[1]); - reference.Set(info[0].As(), info[1]); - } -} - void SetCastedObjects(const CallbackInfo& info) { Env env = info.Env(); HandleScope scope(env); @@ -242,9 +208,57 @@ Value GetFromValue(const CallbackInfo& info) { } } +Value GetHelper(ObjectReference& ref, + Object& configObject, + const Napi::Env& env) { + int keyType = + MaybeUnwrap(configObject.Get("keyType")).As().Uint32Value(); + if (ref.IsEmpty()) { + return String::New(env, "No referenced Value"); + } + + switch (keyType) { + case C_STR: { + std::string c_key = + MaybeUnwrap(configObject.Get("key")).As().Utf8Value(); + return MaybeUnwrap(ref.Get(c_key.c_str())); + break; + } + case CPP_STR: { + std::string cpp_key = + MaybeUnwrap(configObject.Get("key")).As().Utf8Value(); + return MaybeUnwrap(ref.Get(cpp_key)); + break; + } + case INT: { + uint32_t key = + MaybeUnwrap(configObject.Get("key")).As().Uint32Value(); + return MaybeUnwrap(ref.Get(key)); + break; + } + + default: + return String::New(env, "Error: Reached end of getter"); + break; + } +} + +Value GetFromGetters(const CallbackInfo& info) { + std::string object_req = info[0].As(); + Object configObject = info[1].As(); + if (object_req == "weak") { + return GetHelper(weak, configObject, info.Env()); + } else if (object_req == "persistent") { + return GetHelper(persistent, configObject, info.Env()); + } + + return GetHelper(reference, configObject, info.Env()); +} + // info[0] is a flag to determine if the weak, persistent, or // multiple reference ObjectReference is being requested. // info[1] is the key, and it be either a String or a Number. +// Idea to refactor: [ 'weak', {keyType: enum.INT, key:'abc'}] Value GetFromGetter(const CallbackInfo& info) { Env env = info.Env(); @@ -363,9 +377,8 @@ Object InitObjectReference(Env env) { exports["setCastedObjects"] = Function::New(env, SetCastedObjects); exports["setObject"] = Function::New(env, SetObject); - exports["setObjects"] = Function::New(env, SetObjects); exports["getCastedFromValue"] = Function::New(env, GetCastedFromValue); - exports["getFromGetter"] = Function::New(env, GetFromGetter); + exports["getFromGetters"] = Function::New(env, GetFromGetters); exports["getCastedFromGetter"] = Function::New(env, GetCastedFromGetter); exports["getFromValue"] = Function::New(env, GetFromValue); exports["unrefObjects"] = Function::New(env, UnrefObjects); diff --git a/test/object_reference.js b/test/object_reference.js index 621ba625c..795e68dd1 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -106,7 +106,7 @@ function test (binding) { for (const configObject of configObjects) { binding.objectreference.setObject(configObject); const test = binding.objectreference.getFromValue('weak'); - const test2 = binding.objectreference.getFromGetter('weak', configObject.key); + const test2 = binding.objectreference.getFromGetters('weak', configObject); const assertObject = { [configObject.key]: configObject.val @@ -115,12 +115,14 @@ function test (binding) { assert.equal(configObject.val, test2); } }, () => { - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); + const configObjA = { keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }; + const configObjB = { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }; + binding.objectreference.setObject(configObjA); + binding.objectreference.setObject(configObjB); const test = binding.objectreference.getFromValue('weak'); - const test2 = binding.objectreference.getFromGetter('weak', 0); - const test3 = binding.objectreference.getFromGetter('weak', 1); + const test2 = binding.objectreference.getFromGetters('weak', configObjA); + const test3 = binding.objectreference.getFromGetters('weak', configObjB); assert.deepEqual({ 1: 'world' }, test); assert.equal(undefined, test2); assert.equal('world', test3); @@ -149,11 +151,11 @@ function test (binding) { for (const configObject of configObjects) { binding.objectreference.setObject(configObject); const test = binding.objectreference.getFromValue('persistent'); - const test2 = binding.objectreference.getFromGetter('persistent', configObject.key); - + const test2 = binding.objectreference.getFromGetters('persistent', configObject); const assertObject = { [configObject.key]: configObject.val }; + assert.deepEqual(assertObject, test); assert.equal(configObject.val, test2); } @@ -168,12 +170,14 @@ function test (binding) { assert.deepEqual(test, test2); }, () => { - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); + const configObjA = { keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }; + const configObjB = { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }; + binding.objectreference.setObject(configObjA); + binding.objectreference.setObject(configObjB); const test = binding.objectreference.getFromValue('persistent'); - const test2 = binding.objectreference.getFromGetter('persistent', 0); - const test3 = binding.objectreference.getFromGetter('persistent', 1); + const test2 = binding.objectreference.getFromGetters('persistent', configObjA); + const test3 = binding.objectreference.getFromGetters('persistent', configObjB); assert.deepEqual({ 1: 'world' }, test); assert.equal(undefined, test2); @@ -209,8 +213,7 @@ function test (binding) { for (const configObject of configObjects) { binding.objectreference.setObject(configObject); const test = binding.objectreference.getFromValue(); - const test2 = binding.objectreference.getFromGetter(configObject.key); - + const test2 = binding.objectreference.getFromGetters('reference', configObject); const assertObject = { [configObject.key]: configObject.val }; @@ -219,11 +222,14 @@ function test (binding) { } }, () => { - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }); - binding.objectreference.setObject({ keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }); + const configObjA = { keyType: enumType.INT, valType: enumType.JS, key: 0, val: 'hello' }; + const configObjB = { keyType: enumType.INT, valType: enumType.JS, key: 1, val: 'world' }; + binding.objectreference.setObject(configObjA); + binding.objectreference.setObject(configObjB); const test = binding.objectreference.getFromValue(); - const test2 = binding.objectreference.getFromGetter(0); - const test3 = binding.objectreference.getFromGetter(1); + + const test2 = binding.objectreference.getFromGetters('reference', configObjA); + const test3 = binding.objectreference.getFromGetters('reference', configObjB); assert.deepEqual({ 1: 'world' }, test); assert.equal(undefined, test2); From c9ddd51caef233fff81f5aec246c16bd087c7abf Mon Sep 17 00:00:00 2001 From: JckXia Date: Sat, 7 Jan 2023 20:08:03 -0500 Subject: [PATCH 6/7] test: Add test covg for std::move operators --- test/object_reference.cc | 37 ++++++++++++++++++++++++++++++++++--- test/object_reference.js | 1 + 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index 39d525b90..f71f2f1c2 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -2,8 +2,7 @@ are not Objects by creating a blank Object and setting Values to it. Subclasses of Objects can only be set using an ObjectReference by first casting it as an Object. */ - -#include +#include "assert.h" #include "napi.h" #include "test_helper.h" @@ -18,7 +17,7 @@ ObjectReference casted_persistent; ObjectReference casted_reference; // Set keys can be one of: -// C style string OR Napi::Value, which we cast to std::string& utf8 +// C style string, std::string& utf8, and const char * // Set values can be one of: // Napi::Value @@ -29,6 +28,37 @@ ObjectReference casted_reference; enum VAL_TYPES { JS = 0, C_STR, CPP_STR, BOOL, INT, DOUBLE, JS_CAST }; +void MoveOperatorsTest(const Napi::CallbackInfo& info) { + Napi::ObjectReference existingRef; + Napi::ObjectReference existingRef2; + Napi::Object testObject = Napi::Object::New(info.Env()); + testObject.Set("testProp", "tProp"); + + // ObjectReference(Reference&& other); + Napi::Reference refObj = + Napi::Reference::New(testObject); + Napi::ObjectReference objRef = std::move(refObj); + std::string prop = MaybeUnwrap(objRef.Get("testProp")).As(); + assert(prop == "tProp"); + + // ObjectReference& operator=(Reference&& other); + Napi::Reference refObj2 = + Napi::Reference::New(testObject); + existingRef = std::move(refObj2); + prop = MaybeUnwrap(existingRef.Get("testProp")).As(); + assert(prop == "tProp"); + + // ObjectReference(ObjectReference&& other); + Napi::ObjectReference objRef3 = std::move(existingRef); + prop = MaybeUnwrap(objRef3.Get("testProp")).As(); + assert(prop == "tProp"); + + // ObjectReference& operator=(ObjectReference&& other); + existingRef2 = std::move(objRef3); + prop = MaybeUnwrap(objRef.Get("testProp")).As(); + assert(prop == "tProp"); +} + void SetObjectWithCStringKey(Napi::ObjectReference& obj, Napi::Value key, Napi::Value val, @@ -383,6 +413,7 @@ Object InitObjectReference(Env env) { exports["getFromValue"] = Function::New(env, GetFromValue); exports["unrefObjects"] = Function::New(env, UnrefObjects); exports["refObjects"] = Function::New(env, RefObjects); + exports["moveOpTest"] = Function::New(env, MoveOperatorsTest); return exports; } diff --git a/test/object_reference.js b/test/object_reference.js index 795e68dd1..8039b3741 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -46,6 +46,7 @@ const configObjects = [ ]; function test (binding) { + binding.objectreference.moveOpTest(); function testCastedEqual (testToCompare) { const compareTest = ['hello', 'world', '!']; if (testToCompare instanceof Array) { From 0e1b2c46aae7be16d7f38a1cc9668359b6ef0390 Mon Sep 17 00:00:00 2001 From: JckXia Date: Sat, 7 Jan 2023 20:12:36 -0500 Subject: [PATCH 7/7] test: Update function name --- test/object_reference.cc | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/object_reference.cc b/test/object_reference.cc index f71f2f1c2..2d3fc4807 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -89,11 +89,10 @@ void SetObjectWithCStringKey(Napi::ObjectReference& obj, } } -// TODO: Change this function name to SetObjectWithCppStringKey -void SetObjectWithJsStringKey(Napi::ObjectReference& obj, - Napi::Value key, - Napi::Value val, - int valType) { +void SetObjectWithCppStringKey(Napi::ObjectReference& obj, + Napi::Value key, + Napi::Value val, + int valType) { std::string c_key = key.As(); switch (valType) { case JS: @@ -180,9 +179,9 @@ void SetObject(const Napi::CallbackInfo& info) { switch (keyType) { case CPP_STR: - SetObjectWithJsStringKey(weak, key, val, valType); - SetObjectWithJsStringKey(persistent, key, val, valType); - SetObjectWithJsStringKey(reference, key, val, valType); + SetObjectWithCppStringKey(weak, key, val, valType); + SetObjectWithCppStringKey(persistent, key, val, valType); + SetObjectWithCppStringKey(reference, key, val, valType); break; case C_STR: @@ -288,7 +287,6 @@ Value GetFromGetters(const CallbackInfo& info) { // info[0] is a flag to determine if the weak, persistent, or // multiple reference ObjectReference is being requested. // info[1] is the key, and it be either a String or a Number. -// Idea to refactor: [ 'weak', {keyType: enum.INT, key:'abc'}] Value GetFromGetter(const CallbackInfo& info) { Env env = info.Env();