From 09f39def6a7d11747602a34e03333cdc69d8cc9e Mon Sep 17 00:00:00 2001 From: JoseExposito Date: Wed, 10 Mar 2021 07:37:07 +0100 Subject: [PATCH] test: dd tests for Function constructors PR-URL: https://github.com/nodejs/node-addon-api/pull/937 Reviewed-By: Michael Dawson --- test/function.cc | 126 ++++++++++++++++++++++++++++++++++++++++++++++- test/function.js | 51 ++++++++++++++++--- 2 files changed, 168 insertions(+), 9 deletions(-) diff --git a/test/function.cc b/test/function.cc index b0ae92c7d..b45e91dd1 100644 --- a/test/function.cc +++ b/test/function.cc @@ -6,6 +6,13 @@ namespace { int testData = 1; +Boolean EmptyConstructor(const CallbackInfo& info) { + auto env = info.Env(); + bool isEmpty = info[0].As(); + Function function = isEmpty ? Function() : Function(env, Object::New(env)); + return Boolean::New(env, function.IsEmpty()); +} + void VoidCallback(const CallbackInfo& info) { auto env = info.Env(); Object obj = info[0].As(); @@ -45,8 +52,9 @@ Value ValueCallbackWithData(const CallbackInfo& info) { } Value CallWithArgs(const CallbackInfo& info) { - Function func = info[0].As(); - return func({ info[1], info[2], info[3] }); + Function func = info[0].As(); + return func.Call( + std::initializer_list{info[1], info[2], info[3]}); } Value CallWithVector(const CallbackInfo& info) { @@ -59,6 +67,27 @@ Value CallWithVector(const CallbackInfo& info) { return func.Call(args); } +Value CallWithCStyleArray(const CallbackInfo& info) { + Function func = info[0].As(); + std::vector args; + args.reserve(3); + args.push_back(info[1]); + args.push_back(info[2]); + args.push_back(info[3]); + return func.Call(args.size(), args.data()); +} + +Value CallWithReceiverAndCStyleArray(const CallbackInfo& info) { + Function func = info[0].As(); + Value receiver = info[1]; + std::vector args; + args.reserve(3); + args.push_back(info[2]); + args.push_back(info[3]); + args.push_back(info[4]); + return func.Call(receiver, args.size(), args.data()); +} + Value CallWithReceiverAndArgs(const CallbackInfo& info) { Function func = info[0].As(); Value receiver = info[1]; @@ -96,17 +125,81 @@ Value CallConstructorWithVector(const CallbackInfo& info) { return func.New(args); } +Value CallConstructorWithCStyleArray(const CallbackInfo& info) { + Function func = info[0].As(); + std::vector args; + args.reserve(3); + args.push_back(info[1]); + args.push_back(info[2]); + args.push_back(info[3]); + return func.New(args.size(), args.data()); +} + void IsConstructCall(const CallbackInfo& info) { Function callback = info[0].As(); bool isConstructCall = info.IsConstructCall(); callback({Napi::Boolean::New(info.Env(), isConstructCall)}); } +void MakeCallbackWithArgs(const CallbackInfo& info) { + Env env = info.Env(); + Function callback = info[0].As(); + Object resource = info[1].As(); + + AsyncContext context(env, "function_test_context", resource); + + callback.MakeCallback( + resource, + std::initializer_list{info[2], info[3], info[4]}, + context); +} + +void MakeCallbackWithVector(const CallbackInfo& info) { + Env env = info.Env(); + Function callback = info[0].As(); + Object resource = info[1].As(); + + AsyncContext context(env, "function_test_context", resource); + + std::vector args; + args.reserve(3); + args.push_back(info[2]); + args.push_back(info[3]); + args.push_back(info[4]); + callback.MakeCallback(resource, args, context); +} + +void MakeCallbackWithCStyleArray(const CallbackInfo& info) { + Env env = info.Env(); + Function callback = info[0].As(); + Object resource = info[1].As(); + + AsyncContext context(env, "function_test_context", resource); + + std::vector args; + args.reserve(3); + args.push_back(info[2]); + args.push_back(info[3]); + args.push_back(info[4]); + callback.MakeCallback(resource, args.size(), args.data(), context); +} + +void MakeCallbackWithInvalidReceiver(const CallbackInfo& info) { + Function callback = info[0].As(); + callback.MakeCallback(Value(), std::initializer_list{}); +} + +Value CallWithFunctionOperator(const CallbackInfo& info) { + Function func = info[0].As(); + return func({info[1], info[2], info[3]}); +} + } // end anonymous namespace Object InitFunction(Env env) { Object result = Object::New(env); Object exports = Object::New(env); + exports["emptyConstructor"] = Function::New(env, EmptyConstructor); exports["voidCallback"] = Function::New(env, VoidCallback, "voidCallback"); exports["valueCallback"] = Function::New(env, ValueCallback, std::string("valueCallback")); exports["voidCallbackWithData"] = @@ -115,15 +208,30 @@ Object InitFunction(Env env) { Function::New(env, ValueCallbackWithData, nullptr, &testData); exports["callWithArgs"] = Function::New(env, CallWithArgs); exports["callWithVector"] = Function::New(env, CallWithVector); + exports["callWithCStyleArray"] = Function::New(env, CallWithCStyleArray); + exports["callWithReceiverAndCStyleArray"] = + Function::New(env, CallWithReceiverAndCStyleArray); exports["callWithReceiverAndArgs"] = Function::New(env, CallWithReceiverAndArgs); exports["callWithReceiverAndVector"] = Function::New(env, CallWithReceiverAndVector); exports["callWithInvalidReceiver"] = Function::New(env, CallWithInvalidReceiver); exports["callConstructorWithArgs"] = Function::New(env, CallConstructorWithArgs); exports["callConstructorWithVector"] = Function::New(env, CallConstructorWithVector); + exports["callConstructorWithCStyleArray"] = + Function::New(env, CallConstructorWithCStyleArray); exports["isConstructCall"] = Function::New(env, IsConstructCall); + exports["makeCallbackWithArgs"] = Function::New(env, MakeCallbackWithArgs); + exports["makeCallbackWithVector"] = + Function::New(env, MakeCallbackWithVector); + exports["makeCallbackWithCStyleArray"] = + Function::New(env, MakeCallbackWithCStyleArray); + exports["makeCallbackWithInvalidReceiver"] = + Function::New(env, MakeCallbackWithInvalidReceiver); + exports["callWithFunctionOperator"] = + Function::New(env, CallWithFunctionOperator); result["plain"] = exports; exports = Object::New(env); + exports["emptyConstructor"] = Function::New(env, EmptyConstructor); exports["voidCallback"] = Function::New(env, "voidCallback"); exports["valueCallback"] = Function::New(env, std::string("valueCallback")); @@ -133,6 +241,9 @@ Object InitFunction(Env env) { Function::New(env, nullptr, &testData); exports["callWithArgs"] = Function::New(env); exports["callWithVector"] = Function::New(env); + exports["callWithCStyleArray"] = Function::New(env); + exports["callWithReceiverAndCStyleArray"] = + Function::New(env); exports["callWithReceiverAndArgs"] = Function::New(env); exports["callWithReceiverAndVector"] = @@ -143,7 +254,18 @@ Object InitFunction(Env env) { Function::New(env); exports["callConstructorWithVector"] = Function::New(env); + exports["callConstructorWithCStyleArray"] = + Function::New(env); exports["isConstructCall"] = Function::New(env); + exports["makeCallbackWithArgs"] = Function::New(env); + exports["makeCallbackWithVector"] = + Function::New(env); + exports["makeCallbackWithCStyleArray"] = + Function::New(env); + exports["makeCallbackWithInvalidReceiver"] = + Function::New(env); + exports["callWithFunctionOperator"] = + Function::New(env); result["templated"] = exports; return result; } diff --git a/test/function.js b/test/function.js index 8ab742c27..d98b1944d 100644 --- a/test/function.js +++ b/test/function.js @@ -8,6 +8,9 @@ test(require(`./build/${buildType}/binding.node`).function.templated); test(require(`./build/${buildType}/binding_noexcept.node`).function.templated); function test(binding) { + assert.strictEqual(binding.emptyConstructor(true), true); + assert.strictEqual(binding.emptyConstructor(false), false); + let obj = {}; assert.deepStrictEqual(binding.voidCallback(obj), undefined); assert.deepStrictEqual(obj, { "foo": "bar" }); @@ -26,26 +29,50 @@ function test(binding) { args = [].slice.call(arguments); } + function makeCallbackTestFunction(receiver, expectedOne, expectedTwo, expectedThree) { + return function callback(one, two, three) { + assert.strictEqual(this, receiver); + assert.strictEqual(one, expectedOne); + assert.strictEqual(two, expectedTwo); + assert.strictEqual(three, expectedThree); + } + } + ret = 4; - assert.equal(binding.callWithArgs(testFunction, 1, 2, 3), 4); + assert.strictEqual(binding.callWithArgs(testFunction, 1, 2, 3), 4); assert.strictEqual(receiver, undefined); assert.deepStrictEqual(args, [ 1, 2, 3 ]); ret = 5; - assert.equal(binding.callWithVector(testFunction, 2, 3, 4), 5); + assert.strictEqual(binding.callWithVector(testFunction, 2, 3, 4), 5); assert.strictEqual(receiver, undefined); assert.deepStrictEqual(args, [ 2, 3, 4 ]); ret = 6; - assert.equal(binding.callWithReceiverAndArgs(testFunction, obj, 3, 4, 5), 6); + assert.strictEqual(binding.callWithReceiverAndArgs(testFunction, obj, 3, 4, 5), 6); assert.deepStrictEqual(receiver, obj); assert.deepStrictEqual(args, [ 3, 4, 5 ]); ret = 7; - assert.equal(binding.callWithReceiverAndVector(testFunction, obj, 4, 5, 6), 7); + assert.strictEqual(binding.callWithReceiverAndVector(testFunction, obj, 4, 5, 6), 7); assert.deepStrictEqual(receiver, obj); assert.deepStrictEqual(args, [ 4, 5, 6 ]); + ret = 8; + assert.strictEqual(binding.callWithCStyleArray(testFunction, 5, 6, 7), ret); + assert.deepStrictEqual(receiver, undefined); + assert.deepStrictEqual(args, [ 5, 6, 7 ]); + + ret = 9; + assert.strictEqual(binding.callWithReceiverAndCStyleArray(testFunction, obj, 6, 7, 8), ret); + assert.deepStrictEqual(receiver, obj); + assert.deepStrictEqual(args, [ 6, 7, 8 ]); + + ret = 10; + assert.strictEqual(binding.callWithFunctionOperator(testFunction, 7, 8, 9), ret); + assert.strictEqual(receiver, undefined); + assert.deepStrictEqual(args, [ 7, 8, 9 ]); + assert.throws(() => { binding.callWithInvalidReceiver(); }, /Invalid (pointer passed as )?argument/); @@ -58,14 +85,18 @@ function test(binding) { assert(obj instanceof testConstructor); assert.deepStrictEqual(args, [ 6, 7, 8 ]); + obj = binding.callConstructorWithCStyleArray(testConstructor, 7, 8, 9); + assert(obj instanceof testConstructor); + assert.deepStrictEqual(args, [ 7, 8, 9 ]); + obj = {}; assert.deepStrictEqual(binding.voidCallbackWithData(obj), undefined); assert.deepStrictEqual(obj, { "foo": "bar", "data": 1 }); assert.deepStrictEqual(binding.valueCallbackWithData(), { "foo": "bar", "data": 1 }); - assert.equal(binding.voidCallback.name, 'voidCallback'); - assert.equal(binding.valueCallback.name, 'valueCallback'); + assert.strictEqual(binding.voidCallback.name, 'voidCallback'); + assert.strictEqual(binding.valueCallback.name, 'valueCallback'); let testConstructCall = undefined; binding.isConstructCall((result) => { testConstructCall = result; }); @@ -73,5 +104,11 @@ function test(binding) { new binding.isConstructCall((result) => { testConstructCall = result; }); assert.ok(testConstructCall); - // TODO: Function::MakeCallback tests + obj = {}; + binding.makeCallbackWithArgs(makeCallbackTestFunction(obj, "1", "2", "3"), obj, "1", "2", "3"); + binding.makeCallbackWithVector(makeCallbackTestFunction(obj, 4, 5, 6), obj, 4, 5, 6); + binding.makeCallbackWithCStyleArray(makeCallbackTestFunction(obj, 7, 8, 9), obj, 7, 8, 9); + assert.throws(() => { + binding.makeCallbackWithInvalidReceiver(() => {}); + }); }