-
Notifications
You must be signed in to change notification settings - Fork 467
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/node_modules | ||
/build |
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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
'use strict'; | ||
|
||
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; | ||
}); | ||
|
||
let err = binding.error.catchError( | ||
() => { throw new TypeError('test'); }); | ||
assert(err instanceof TypeError); | ||
assert.equal(err.message, 'test'); | ||
|
||
let msg = binding.error.catchErrorMessage( | ||
() => { throw new TypeError('test'); }); | ||
assert.equal(msg, 'test'); |
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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
'use strict'; | ||
|
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,18 @@ | ||
'use strict'; | ||
const binding = require('./build/Release/binding.node'); | ||
const assert = require('assert'); | ||
global.buildType = process.config.target_defaults.default_configuration; | ||
global.binding = require(`./build/${buildType}/binding.node`); | ||
global.assert = require('assert'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that somebody looking at the test files themselves might need to look up where those “magic” globals come from … I’d be very okay with just copying these lines into the test files themselves :) That would also have the advantage that they are are runnable as standalone node scripts, which might be nice when the test suite is bigger and takes longer to run. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I didn't really like this use of global either. Ability to run the test files individually is a good point. |
||
|
||
assert.deepStrictEqual(binding.test1(), { "foo": "bar" }); | ||
let testModules = [ | ||
'error', | ||
'function', | ||
]; | ||
|
||
testModules.forEach(name => { | ||
try { | ||
require('./' + name); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just fyi, this is how we’d write this in Node core right now:
(
const
wherever possible, block scope + always using strict equality asserts)