From 4027196bf27639200c3d1ce252ccfe15928aaa03 Mon Sep 17 00:00:00 2001 From: Roy Wright Date: Fri, 1 Dec 2017 00:46:54 +0900 Subject: [PATCH] test: Write tests for Value class This change includes the following new tests: - TypeChecker(e.g. IsUndefined, IsObject) tests - TypeConverter from Native to JS(e.g. ToString) tests PR-URL: https://github.com/nodejs/node-addon-api/pull/197 Reviewed-By: Michael Dawson --- test/basic_types/value.cc | 96 +++++++++++++++++++++++++++++++ test/basic_types/value.js | 116 ++++++++++++++++++++++++++++++++++++++ test/binding.cc | 2 + test/binding.gyp | 1 + test/index.js | 1 + 5 files changed, 216 insertions(+) create mode 100644 test/basic_types/value.cc create mode 100644 test/basic_types/value.js diff --git a/test/basic_types/value.cc b/test/basic_types/value.cc new file mode 100644 index 0000000..b2f1b5b --- /dev/null +++ b/test/basic_types/value.cc @@ -0,0 +1,96 @@ +#include "napi.h" + +using namespace Napi; + +static Value IsEmpty(const CallbackInfo& info) { + Value value; + return Boolean::New(info.Env(), value.IsEmpty()); +} + +static Value IsUndefined(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsUndefined()); +} + +static Value IsNull(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsNull()); +} + +static Value IsBoolean(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsBoolean()); +} + +static Value IsNumber(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsNumber()); +} + +static Value IsString(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsString()); +} + +static Value IsSymbol(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsSymbol()); +} + +static Value IsArray(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsArray()); +} + +static Value IsArrayBuffer(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsArrayBuffer()); +} + +static Value IsTypedArray(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsTypedArray()); +} + +static Value IsObject(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsObject()); +} + +static Value IsFunction(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsFunction()); +} + +static Value IsPromise(const CallbackInfo& info) { + return Boolean::New(info.Env(), info[0].IsPromise()); +} + +static Value ToBoolean(const CallbackInfo& info) { + return info[0].ToBoolean(); +} + +static Value ToNumber(const CallbackInfo& info) { + return info[0].ToNumber(); +} + +static Value ToString(const CallbackInfo& info) { + return info[0].ToString(); +} + +static Value ToObject(const CallbackInfo& info) { + return info[0].ToObject(); +} + +Object InitBasicTypesValue(Env env) { + Object exports = Object::New(env); + + exports["isEmpty"] = Function::New(env, IsEmpty); + exports["isUndefined"] = Function::New(env, IsUndefined); + exports["isNull"] = Function::New(env, IsNull); + exports["isBoolean"] = Function::New(env, IsBoolean); + exports["isNumber"] = Function::New(env, IsNumber); + exports["isString"] = Function::New(env, IsString); + exports["isSymbol"] = Function::New(env, IsSymbol); + exports["isArray"] = Function::New(env, IsArray); + exports["isArrayBuffer"] = Function::New(env, IsArrayBuffer); + exports["isTypedArray"] = Function::New(env, IsTypedArray); + exports["isObject"] = Function::New(env, IsObject); + exports["isFunction"] = Function::New(env, IsFunction); + exports["isPromise"] = Function::New(env, IsPromise); + exports["toBoolean"] = Function::New(env, ToBoolean); + exports["toNumber"] = Function::New(env, ToNumber); + exports["toString"] = Function::New(env, ToString); + exports["toObject"] = Function::New(env, ToObject); + + return exports; +} diff --git a/test/basic_types/value.js b/test/basic_types/value.js new file mode 100644 index 0000000..17fd8ec --- /dev/null +++ b/test/basic_types/value.js @@ -0,0 +1,116 @@ +'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 detailedTypeOf(value) { + const type = typeof value; + if (type !== 'object') + return type; + + if (value === null) + return 'null'; + + if (Array.isArray(value)) + return 'array'; + + if (!value.constructor) + return type; + + if (value instanceof ArrayBuffer) + return 'arraybuffer'; + + if (ArrayBuffer.isView(value)) + return 'typedarray'; + + if (value instanceof Promise) + return 'promise'; + + return 'object'; + } + + function typeCheckerTest(typeChecker, expectedType) { + const testValueList = [ + undefined, + null, + true, + 10, + 'string', + Symbol('symbol'), + [], + new ArrayBuffer(10), + new Int32Array(new ArrayBuffer(12)), + {}, + function() {}, + new Promise((resolve, reject) => {}) + ]; + + testValueList.forEach((testValue) => { + if (testValue !== null && expectedType === 'object') { + assert.strictEqual(typeChecker(testValue), typeof testValue === expectedType); + } else { + assert.strictEqual(typeChecker(testValue), detailedTypeOf(testValue) === expectedType); + } + }); + } + + function typeConverterTest(typeConverter, expectedType) { + const testValueList = [ + true, + false, + 0, + 10, + 'string', + [], + new ArrayBuffer(10), + new Int32Array(new ArrayBuffer(12)), + {}, + function() {}, + new Promise((resolve, reject) => {}) + ]; + + testValueList.forEach((testValue) => { + const expected = expectedType(testValue); + const actual = typeConverter(testValue); + + if (isNaN(expected)) { + assert(isNaN(actual)); + } else { + assert.deepStrictEqual(typeConverter(testValue), expectedType(testValue)); + } + }); + } + + const value = binding.basic_types_value; + + typeCheckerTest(value.isUndefined, 'undefined'); + typeCheckerTest(value.isNull, 'null'); + typeCheckerTest(value.isBoolean, 'boolean'); + typeCheckerTest(value.isNumber, 'number'); + typeCheckerTest(value.isString, 'string'); + typeCheckerTest(value.isSymbol, 'symbol'); + typeCheckerTest(value.isArray, 'array'); + typeCheckerTest(value.isArrayBuffer, 'arraybuffer'); + typeCheckerTest(value.isTypedArray, 'typedarray'); + typeCheckerTest(value.isObject, 'object'); + typeCheckerTest(value.isFunction, 'function'); + typeCheckerTest(value.isPromise, 'promise'); + + typeConverterTest(value.toBoolean, Boolean); + assert.strictEqual(value.toBoolean(undefined), false); + assert.strictEqual(value.toBoolean(null), false); + + typeConverterTest(value.toNumber, Number); + assert(isNaN(value.toNumber(undefined))); + assert.strictEqual(value.toNumber(null), 0); + + typeConverterTest(value.toString, String); + assert.strictEqual(value.toString(undefined), 'undefined'); + assert.strictEqual(value.toString(null), 'null'); + + typeConverterTest(value.toObject, Object); +} diff --git a/test/binding.cc b/test/binding.cc index c18d045..3f08d33 100644 --- a/test/binding.cc +++ b/test/binding.cc @@ -5,6 +5,7 @@ using namespace Napi; Object InitArrayBuffer(Env env); Object InitAsyncWorker(Env env); Object InitBasicTypesNumber(Env env); +Object InitBasicTypesValue(Env env); Object InitBuffer(Env env); Object InitError(Env env); Object InitExternal(Env env); @@ -19,6 +20,7 @@ Object Init(Env env, Object exports) { exports.Set("arraybuffer", InitArrayBuffer(env)); exports.Set("asyncworker", InitAsyncWorker(env)); exports.Set("basic_types_number", InitBasicTypesNumber(env)); + exports.Set("basic_types_value", InitBasicTypesValue(env)); exports.Set("buffer", InitBuffer(env)); exports.Set("error", InitError(env)); exports.Set("external", InitExternal(env)); diff --git a/test/binding.gyp b/test/binding.gyp index 7a97f91..45d8d0b 100644 --- a/test/binding.gyp +++ b/test/binding.gyp @@ -4,6 +4,7 @@ 'arraybuffer.cc', 'asyncworker.cc', 'basic_types/number.cc', + 'basic_types/value.cc', 'binding.cc', 'buffer.cc', 'error.cc', diff --git a/test/index.js b/test/index.js index f8e17a7..f772d18 100644 --- a/test/index.js +++ b/test/index.js @@ -11,6 +11,7 @@ let testModules = [ 'arraybuffer', 'asyncworker', 'basic_types/number', + 'basic_types/value', 'buffer', 'error', 'external',