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

Set up unit tests #24

Merged
merged 2 commits into from
Apr 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
/build
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ backward-compatibility with use with older versions of Node.js that do
not have N-API built-in.

To use N-API in a native module:
1. Add a dependency on this package to `package.json`.
1. Add a dependency on this package to `package.json`.
It is not yet published to npm, so reference it directly from GitHub.
```json
"dependencies": {
Expand All @@ -27,6 +27,9 @@ To use N-API in a native module:
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES' },
'msvs_settings': {
'VCCLCompilerTool': { 'ExceptionHandling': 1 },
},
```

4. Include `napi.h` in the native module code.
Expand Down
2 changes: 1 addition & 1 deletion napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1682,7 +1682,7 @@ inline const Value CallbackInfo::operator [](size_t index) const {
return index < _argc ? Value(_env, _argv[index]) : Env().Undefined();
}

inline Object CallbackInfo::This() const {
inline Value CallbackInfo::This() const {
if (_this == nullptr) {
return Env().Undefined();
}
Expand Down
2 changes: 1 addition & 1 deletion napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ namespace Napi {
Napi::Env Env() const;
size_t Length() const;
const Value operator [](size_t index) const;
Object This() const;
Value This() const;
void* Data() const;
void SetData(void* data);

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {},
"description": "Node.js API (N-API)",
"devDependencies": {
"node-gyp": "^3.6.0"
},
"directories": {},
"homepage": "https://github.com/nodejs/node-api",
Expand All @@ -18,6 +19,8 @@
"url": "git://github.com/nodejs/node-api.git"
},
"scripts": {
"pretest": "node-gyp rebuild -C test",
"test": "node test"
},
"version": "0.1.0"
}
13 changes: 4 additions & 9 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@

using namespace Napi;

Value Test1(const CallbackInfo& info) {
auto env = info.Env();
Object obj = Object::New(env);

obj["foo"] = String::New(env, "bar");

return obj;
}
Object InitError(Env env);
Object InitFunction(Env env);

void Init(Env env, Object exports, Object module) {
exports.Set("test1", Function::New(env, Test1));
exports.Set("error", InitError(env));
exports.Set("function", InitFunction(env));
}

NODE_API_MODULE(addon, Init)
15 changes: 11 additions & 4 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
'targets': [
{
'target_name': 'binding',
'sources': [ 'binding.cc' ],
'include_dirs': ['<!(node -p \'require("../").include\')'],
'dependencies': ['<!(node -p \'require("../").gyp\')'],
'sources': [
'binding.cc',
'error.cc',
'function.cc',
],
'include_dirs': ["<!(node -p \"require('../').include\")"],
'dependencies': ["<!(node -p \"require('../').gyp\")"],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES' }
'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES' },
'msvs_settings': {
'VCCLCompilerTool': { 'ExceptionHandling': 1 },
},
}
]
}
66 changes: 66 additions & 0 deletions test/error.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "napi.h"

using namespace Napi;

void ThrowError(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();
throw Error::New(info.Env(), message);
}

void ThrowTypeError(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();
throw TypeError::New(info.Env(), message);
}

void ThrowRangeError(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();
throw RangeError::New(info.Env(), message);
}

Value CatchError(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
try {
thrower({});
} catch (const Error& e) {
return e;
}
return info.Env().Null();
}

Value CatchErrorMessage(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
try {
thrower({});
} catch (const Error& e) {
std::string message = e.Message();
return String::New(info.Env(), message);
}
return info.Env().Null();
}

void DoNotCatch(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
thrower({});
}

void CatchAndRethrowError(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
try {
thrower({});
} catch (Error& e) {
e["caught"] = Boolean::New(info.Env(), true);
throw e;
}
}

Object InitError(Env env) {
Object exports = Object::New(env);
exports["throwError"] = Function::New(env, ThrowError);
exports["throwTypeError"] = Function::New(env, ThrowTypeError);
exports["throwRangeError"] = Function::New(env, ThrowRangeError);
exports["catchError"] = Function::New(env, CatchError);
exports["catchErrorMessage"] = Function::New(env, CatchErrorMessage);
exports["doNotCatch"] = Function::New(env, DoNotCatch);
exports["catchAndRethrowError"] = Function::New(env, CatchAndRethrowError);
return exports;
}
43 changes: 43 additions & 0 deletions test/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';
const buildType = process.config.target_defaults.default_configuration;
const binding = require(`./build/${buildType}/binding.node`);
const assert = require('assert');

assert.throws(() => binding.error.throwError('test'), err => {
return err instanceof Error && err.message === 'test';
});

assert.throws(() => binding.error.throwTypeError('test'), err => {
return err instanceof TypeError && err.message === 'test';
});

assert.throws(() => binding.error.throwRangeError('test'), err => {
return err instanceof RangeError && err.message === 'test';
});

assert.throws(
() => binding.error.doNotCatch(
() => {
throw new TypeError('test');
}),
err => {
return err instanceof TypeError && err.message === 'test' && !err.caught;
});

assert.throws(
() => binding.error.catchAndRethrowError(
() => {
throw new TypeError('test');
}),
err => {
return err instanceof TypeError && err.message === 'test' && err.caught;
});

const err = binding.error.catchError(
() => { throw new TypeError('test'); });
assert(err instanceof TypeError);
assert.strictEqual(err.message, 'test');

const msg = binding.error.catchErrorMessage(
() => { throw new TypeError('test'); });
assert.strictEqual(msg, 'test');
79 changes: 79 additions & 0 deletions test/function.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "napi.h"

using namespace Napi;

void VoidCallback(const CallbackInfo& info) {
auto env = info.Env();
Object obj = info[0].As<Object>();

obj["foo"] = String::New(env, "bar");
}

Value ValueCallback(const CallbackInfo& info) {
auto env = info.Env();
Object obj = Object::New(env);

obj["foo"] = String::New(env, "bar");

return obj;
}

Value CallWithArgs(const CallbackInfo& info) {
Function func = info[0].As<Function>();
return func({ info[1], info[2], info[3] });
}

Value CallWithVector(const CallbackInfo& info) {
Function func = info[0].As<Function>();
std::vector<napi_value> args;
args.reserve(3);
args.push_back(info[1]);
args.push_back(info[2]);
args.push_back(info[3]);
return func.Call(args);
}

Value CallWithReceiverAndArgs(const CallbackInfo& info) {
Function func = info[0].As<Function>();
Value receiver = info[1];
return func.Call(receiver, { info[2], info[3], info[4] });
}

Value CallWithReceiverAndVector(const CallbackInfo& info) {
Function func = info[0].As<Function>();
Value receiver = info[1];
std::vector<napi_value> args;
args.reserve(3);
args.push_back(info[2]);
args.push_back(info[3]);
args.push_back(info[4]);
return func.Call(receiver, args);
}

Value CallConstructorWithArgs(const CallbackInfo& info) {
Function func = info[0].As<Function>();
return func.New({ info[1], info[2], info[3] });
}

Value CallConstructorWithVector(const CallbackInfo& info) {
Function func = info[0].As<Function>();
std::vector<napi_value> args;
args.reserve(3);
args.push_back(info[1]);
args.push_back(info[2]);
args.push_back(info[3]);
return func.New(args);
}

Object InitFunction(Env env) {
Object exports = Object::New(env);
exports["voidCallback"] = Function::New(env, VoidCallback, "voidCallback");
exports["valueCallback"] = Function::New(env, ValueCallback, std::string("valueCallback"));
exports["callWithArgs"] = Function::New(env, CallWithArgs);
exports["callWithVector"] = Function::New(env, CallWithVector);
exports["callWithReceiverAndArgs"] = Function::New(env, CallWithReceiverAndArgs);
exports["callWithReceiverAndVector"] = Function::New(env, CallWithReceiverAndVector);
exports["callConstructorWithArgs"] = Function::New(env, CallConstructorWithArgs);
exports["callConstructorWithVector"] = Function::New(env, CallConstructorWithVector);
return exports;
}
55 changes: 55 additions & 0 deletions test/function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';
const buildType = process.config.target_defaults.default_configuration;
const binding = require(`./build/${buildType}/binding.node`);
const assert = require('assert');

let obj = {};
assert.deepStrictEqual(binding.function.voidCallback(obj), undefined);
assert.deepStrictEqual(obj, { "foo": "bar" });

assert.deepStrictEqual(binding.function.valueCallback(), { "foo": "bar" });

let args = null;
let ret = null;
let receiver = null;
function testFunction() {
receiver = this;
args = [].slice.call(arguments);
return ret;
}
function testConstructor() {
args = [].slice.call(arguments);
}

ret = 4;
assert.equal(binding.function.callWithArgs(testFunction, 1, 2, 3), 4);
assert.strictEqual(receiver, undefined);
assert.deepStrictEqual(args, [ 1, 2, 3 ]);

ret = 5;
assert.equal(binding.function.callWithVector(testFunction, 2, 3, 4), 5);
assert.strictEqual(receiver, undefined);
assert.deepStrictEqual(args, [ 2, 3, 4 ]);

ret = 6;
assert.equal(binding.function.callWithReceiverAndArgs(testFunction, obj, 3, 4, 5), 6);
assert.deepStrictEqual(receiver, obj);
assert.deepStrictEqual(args, [ 3, 4, 5 ]);

ret = 7;
assert.equal(binding.function.callWithReceiverAndVector(testFunction, obj, 4, 5, 6), 7);
assert.deepStrictEqual(receiver, obj);
assert.deepStrictEqual(args, [ 4, 5, 6 ]);

obj = binding.function.callConstructorWithArgs(testConstructor, 5, 6, 7);
assert(obj instanceof testConstructor);
assert.deepStrictEqual(args, [ 5, 6, 7 ]);

obj = binding.function.callConstructorWithVector(testConstructor, 6, 7, 8);
assert(obj instanceof testConstructor);
assert.deepStrictEqual(args, [ 6, 7, 8 ]);

assert.equal(binding.function.voidCallback.name, 'voidCallback');
assert.equal(binding.function.valueCallback.name, 'valueCallback');

// TODO: Function::MakeCallback tests
16 changes: 13 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
'use strict';
const binding = require('./build/Release/binding.node');
const assert = require('assert');

assert.deepStrictEqual(binding.test1(), { "foo": "bar" });
let testModules = [
'error',
'function',
];

testModules.forEach(name => {
try {
require('./' + name);
}
catch (e) {
console.error(e);
}
});