Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Object missing tests #923

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'object/has_property.cc',
'object/object.cc',
'object/set_property.cc',
'object/subscript_operator.cc',
'promise.cc',
'run_script.cc',
'threadsafe_function/threadsafe_function_ctx.cc',
Expand Down
24 changes: 16 additions & 8 deletions test/object/get_property.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@ function test(binding) {
assert.strictEqual(nativeGetProperty(obj, 'test'), 1);
}

function testShouldReturnUndefinedIfKeyIsNotPresent(nativeGetProperty) {
const obj = { };
assert.strictEqual(nativeGetProperty(obj, 'test'), undefined);
}

function testShouldThrowErrorIfKeyIsInvalid(nativeGetProperty) {
assert.throws(() => {
nativeGetProperty(undefined, 'test');
}, /Cannot convert undefined or null to object/);
}

testGetProperty(binding.object.getPropertyWithNapiValue);
testGetProperty(binding.object.getPropertyWithNapiWrapperValue);
testGetProperty(binding.object.getPropertyWithCStyleString);
testGetProperty(binding.object.getPropertyWithCppStyleString);
const nativeFunctions = [
binding.object.getPropertyWithNapiValue,
binding.object.getPropertyWithNapiWrapperValue,
binding.object.getPropertyWithCStyleString,
binding.object.getPropertyWithCppStyleString
];

testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithNapiValue);
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithNapiWrapperValue);
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithCStyleString);
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithCppStyleString);
nativeFunctions.forEach((nativeFunction) => {
testGetProperty(nativeFunction);
testShouldReturnUndefinedIfKeyIsNotPresent(nativeFunction);
testShouldThrowErrorIfKeyIsInvalid(nativeFunction);
});
}
43 changes: 43 additions & 0 deletions test/object/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ Value HasPropertyWithCppStyleString(const CallbackInfo& info);
Value AddFinalizer(const CallbackInfo& info);
Value AddFinalizerWithHint(const CallbackInfo& info);

// Native wrappers for testing Object::operator []
Value SubscriptGetWithCStyleString(const CallbackInfo& info);
Value SubscriptGetWithCppStyleString(const CallbackInfo& info);
Value SubscriptGetAtIndex(const CallbackInfo& info);
void SubscriptSetWithCStyleString(const CallbackInfo& info);
void SubscriptSetWithCppStyleString(const CallbackInfo& info);
void SubscriptSetAtIndex(const CallbackInfo& info);

static bool testValue = true;
// Used to test void* Data() integrity
struct UserDataHolder {
Expand Down Expand Up @@ -69,6 +77,19 @@ Value TestFunctionWithUserData(const CallbackInfo& info) {
return Number::New(info.Env(), holder->value);
}

Value EmptyConstructor(const CallbackInfo& info) {
auto env = info.Env();
bool isEmpty = info[0].As<Boolean>();
Object object = isEmpty ? Object() : Object(env, Object::New(env));
return Boolean::New(env, object.IsEmpty());
}

Value ConstructorFromObject(const CallbackInfo& info) {
auto env = info.Env();
Object object = info[0].As<Object>();
return Object(env, object);
}

Array GetPropertyNames(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
Array arr = obj.GetPropertyNames();
Expand Down Expand Up @@ -228,9 +249,18 @@ Value CreateObjectUsingMagic(const CallbackInfo& info) {
return obj;
}

Value InstanceOf(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
Function constructor = info[1].As<Function>();
return Boolean::New(info.Env(), obj.InstanceOf(constructor));
}

Object InitObject(Env env) {
Object exports = Object::New(env);

exports["emptyConstructor"] = Function::New(env, EmptyConstructor);
exports["constructorFromObject"] = Function::New(env, ConstructorFromObject);

exports["GetPropertyNames"] = Function::New(env, GetPropertyNames);
exports["defineProperties"] = Function::New(env, DefineProperties);
exports["defineValueProperty"] = Function::New(env, DefineValueProperty);
Expand Down Expand Up @@ -265,5 +295,18 @@ Object InitObject(Env env) {
exports["addFinalizer"] = Function::New(env, AddFinalizer);
exports["addFinalizerWithHint"] = Function::New(env, AddFinalizerWithHint);

exports["instanceOf"] = Function::New(env, InstanceOf);

exports["subscriptGetWithCStyleString"] =
Function::New(env, SubscriptGetWithCStyleString);
exports["subscriptGetWithCppStyleString"] =
Function::New(env, SubscriptGetWithCppStyleString);
exports["subscriptGetAtIndex"] = Function::New(env, SubscriptGetAtIndex);
exports["subscriptSetWithCStyleString"] =
Function::New(env, SubscriptSetWithCStyleString);
exports["subscriptSetWithCppStyleString"] =
Function::New(env, SubscriptSetWithCppStyleString);
exports["subscriptSetAtIndex"] = Function::New(env, SubscriptSetAtIndex);

return exports;
}
25 changes: 23 additions & 2 deletions test/object/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ function test(binding) {
testDefineProperties('string');
testDefineProperties('value');

{
assert.strictEqual(binding.object.emptyConstructor(true), true);
assert.strictEqual(binding.object.emptyConstructor(false), false);
}

{
const expected = { 'one': 1, 'two': 2, 'three': 3 };
const actual = binding.object.constructorFromObject(expected);
assert.deepStrictEqual(actual, expected);
}

{
const obj = {};
const testSym = Symbol();
Expand All @@ -110,9 +121,10 @@ function test(binding) {
}

{
const obj = {'one': 1, 'two': 2, 'three': 3};
const testSym = Symbol();
const obj = { 'one': 1, 'two': 2, 'three': 3, [testSym]: 4 };
var arr = binding.object.GetPropertyNames(obj);
assert.deepStrictEqual(arr, ['one', 'two', 'three'])
assert.deepStrictEqual(arr, ['one', 'two', 'three']);
}

{
Expand All @@ -136,4 +148,13 @@ function test(binding) {
circular2: magicObject
});
}

{
function Ctor() {};

assert.strictEqual(binding.object.instanceOf(new Ctor(), Ctor), true);
assert.strictEqual(binding.object.instanceOf(new Ctor(), Object), true);
assert.strictEqual(binding.object.instanceOf({}, Ctor), false);
assert.strictEqual(binding.object.instanceOf(null, Ctor), false);
}
}
42 changes: 42 additions & 0 deletions test/object/subscript_operator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "napi.h"

using namespace Napi;

Value SubscriptGetWithCStyleString(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
String jsKey = info[1].As<String>();
return obj[jsKey.Utf8Value().c_str()];
}

Value SubscriptGetWithCppStyleString(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
String jsKey = info[1].As<String>();
return obj[jsKey.Utf8Value()];
}

Value SubscriptGetAtIndex(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
uint32_t index = info[1].As<Napi::Number>();
return obj[index];
}

void SubscriptSetWithCStyleString(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
String jsKey = info[1].As<String>();
Value value = info[2];
obj[jsKey.Utf8Value().c_str()] = value;
}

void SubscriptSetWithCppStyleString(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
String jsKey = info[1].As<String>();
Value value = info[2];
obj[jsKey.Utf8Value()] = value;
}

void SubscriptSetAtIndex(const CallbackInfo& info) {
Object obj = info[0].As<Object>();
uint32_t index = info[1].As<Napi::Number>();
Value value = info[2];
obj[index] = value;
}
19 changes: 19 additions & 0 deletions test/object/subscript_operator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const buildType = process.config.target_defaults.default_configuration;
const assert = require('assert');

test(require(`../build/${buildType}/binding.node`));
test(require(`../build/${buildType}/binding_noexcept.node`));

function test(binding) {
function testProperty(obj, key, value, nativeGetProperty, nativeSetProperty) {
nativeSetProperty(obj, key, value);
assert.strictEqual(nativeGetProperty(obj, key), value);
}

testProperty({}, 'key', 'value', binding.object.subscriptGetWithCStyleString, binding.object.subscriptSetWithCStyleString);
testProperty({ key: 'override me' }, 'key', 'value', binding.object.subscriptGetWithCppStyleString, binding.object.subscriptSetWithCppStyleString);
testProperty({}, 0, 'value', binding.object.subscriptGetAtIndex, binding.object.subscriptSetAtIndex);
JoseExposito marked this conversation as resolved.
Show resolved Hide resolved
testProperty({ key: 'override me' }, 0, 'value', binding.object.subscriptGetAtIndex, binding.object.subscriptSetAtIndex);
}