From 225ca359636b298b44bc4a8c6a3078977f1992c3 Mon Sep 17 00:00:00 2001 From: Jack <32422811+JckXia@users.noreply.github.com> Date: Fri, 2 Sep 2022 12:07:37 -0400 Subject: [PATCH] test: Add test coverage for "TSFN::Ref()" (#1196) * test:Reference the tsfn * test: Add a more sophiscated test case for ref * test: Unref tsfn before ref'n it again * test: Using different function overload --- .../typed_threadsafe_function_unref.cc | 14 +++ .../typed_threadsafe_function_unref.js | 103 +++++++++++++----- 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc b/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc index 2d137328e..b6588e29f 100644 --- a/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc +++ b/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc @@ -32,6 +32,7 @@ static Value TestUnref(const CallbackInfo& info) { static_cast(nullptr)); tsfn->BlockingCall(); + tsfn->Ref(info.Env()); setTimeout.Call( global, @@ -42,11 +43,24 @@ static Value TestUnref(const CallbackInfo& info) { return info.Env().Undefined(); } +static Value TestRef(const CallbackInfo& info) { + Function cb = info[1].As(); + + auto tsfn = TSFN::New(info.Env(), cb, "testRes", 1, 1, nullptr); + + tsfn.BlockingCall(); + tsfn.Unref(info.Env()); + tsfn.Ref(info.Env()); + + return info.Env().Undefined(); +} + } // namespace Object InitTypedThreadSafeFunctionUnref(Env env) { Object exports = Object::New(env); exports["testUnref"] = Function::New(env, TestUnref); + exports["testRef"] = Function::New(env, TestRef); return exports; } diff --git a/test/typed_threadsafe_function/typed_threadsafe_function_unref.js b/test/typed_threadsafe_function/typed_threadsafe_function_unref.js index 5566d0b1a..88bf7d340 100644 --- a/test/typed_threadsafe_function/typed_threadsafe_function_unref.js +++ b/test/typed_threadsafe_function/typed_threadsafe_function_unref.js @@ -11,43 +11,88 @@ const isMainProcess = process.argv[1] !== __filename; * - Child process: creates TSFN. Native module Unref's via setTimeout after some time but does NOT call Release. * * Main process should expect child process to exit. + * + * We also added a new test case for `Ref`. The idea being, if a TSFN is active, the event loop that it belongs to should not exit + * Our setup is similar to the test for the `Unref` case, with the difference being now we are expecting the child process to hang */ if (isMainProcess) { module.exports = require('../common').runTestWithBindingPath(test); } else { - test(process.argv[2]); + const isTestingRef = (process.argv[3] === 'true'); + + if (isTestingRef) { + execTSFNRefTest(process.argv[2]); + } else { + execTSFNUnrefTest(process.argv[2]); + } +} + +function testUnRefCallback (resolve, reject, bindingFile) { + const child = require('../napi_child').spawn(process.argv[0], [ + '--expose-gc', __filename, bindingFile, false + ], { stdio: 'inherit' }); + + let timeout = setTimeout(function () { + child.kill(); + timeout = 0; + reject(new Error('Expected child to die')); + }, 5000); + + child.on('error', (err) => { + clearTimeout(timeout); + timeout = 0; + reject(new Error(err)); + }); + + child.on('close', (code) => { + if (timeout) clearTimeout(timeout); + assert.strictEqual(code, 0, 'Expected return value 0'); + resolve(); + }); +} + +function testRefCallback (resolve, reject, bindingFile) { + const child = require('../napi_child').spawn(process.argv[0], [ + '--expose-gc', __filename, bindingFile, true + ], { stdio: 'inherit' }); + + let timeout = setTimeout(function () { + child.kill(); + timeout = 0; + resolve(); + }, 1000); + + child.on('error', (err) => { + clearTimeout(timeout); + timeout = 0; + reject(new Error(err)); + }); + + child.on('close', (code) => { + if (timeout) clearTimeout(timeout); + + reject(new Error('We expected Child to hang')); + }); } function test (bindingFile) { - if (isMainProcess) { - // Main process + // Main process + return new Promise((resolve, reject) => { + testUnRefCallback(resolve, reject, bindingFile); + }).then(() => { return new Promise((resolve, reject) => { - const child = require('../napi_child').spawn(process.argv[0], [ - '--expose-gc', __filename, bindingFile - ], { stdio: 'inherit' }); - - let timeout = setTimeout(function () { - child.kill(); - timeout = 0; - reject(new Error('Expected child to die')); - }, 5000); - - child.on('error', (err) => { - clearTimeout(timeout); - timeout = 0; - reject(new Error(err)); - }); - - child.on('close', (code) => { - if (timeout) clearTimeout(timeout); - assert.strictEqual(code, 0, 'Expected return value 0'); - resolve(); - }); + testRefCallback(resolve, reject, bindingFile); }); - } else { - // Child process - const binding = require(bindingFile); - binding.typed_threadsafe_function_unref.testUnref({}, () => { }); - } + }); +} + +function execTSFNUnrefTest (bindingFile) { + const binding = require(bindingFile); + binding.typed_threadsafe_function_unref.testUnref({}, () => { }); +} + +function execTSFNRefTest (bindingFile) { + const binding = require(bindingFile); + binding.typed_threadsafe_function_unref.testRef({}, () => { }); }