From e2726193f14a268927a3589c3c9396aa3f0efb20 Mon Sep 17 00:00:00 2001 From: JckXia Date: Mon, 26 Dec 2022 16:06:33 -0500 Subject: [PATCH] src: remove AsyncWorker move and complete tests - Remove AsyncWorker move operators. These cannot work properly due to the linkage between the node-api and node-addon-api components - Complete async worker test coverage for recv PR-URL: https://github.com/nodejs/node-addon-api/pull/1266 Reviewed-By: Michael Dawson (); + Function cb = info[1].As(); + + TestWorkerWithUserDefRecv* worker = new TestWorkerWithUserDefRecv(recv, cb); + worker->Queue(); + } + + static void DoWorkWithAsyncRes(const CallbackInfo& info) { + Object recv = info[0].As(); + Function cb = info[1].As(); + Object resource = info[2].As(); + + TestWorkerWithUserDefRecv* worker = nullptr; + if (resource == info.Env().Null()) { + worker = new TestWorkerWithUserDefRecv(recv, cb, "TestResource"); + } else { + worker = + new TestWorkerWithUserDefRecv(recv, cb, "TestResource", resource); + } + + worker->Queue(); + } + + protected: + void Execute() override {} + + private: + TestWorkerWithUserDefRecv(const Object& recv, const Function& cb) + : AsyncWorker(recv, cb) {} + TestWorkerWithUserDefRecv(const Object& recv, + const Function& cb, + const char* resource_name) + : AsyncWorker(recv, cb, resource_name) {} + TestWorkerWithUserDefRecv(const Object& recv, + const Function& cb, + const char* resource_name, + const Object& resource) + : AsyncWorker(recv, cb, resource_name, resource) {} +}; + +// Using default std::allocator impl, but assuming user can define their own +// alloc/dealloc methods +class CustomAllocWorker : public AsyncWorker { + public: + CustomAllocWorker(Function& cb) : AsyncWorker(cb){}; + static void DoWork(const CallbackInfo& info) { + Function cb = info[0].As(); + std::allocator create_alloc; + CustomAllocWorker* newWorker = create_alloc.allocate(1); + create_alloc.construct(newWorker, cb); + newWorker->Queue(); + } + + protected: + void Execute() override {} + void Destroy() override { + assert(this->_secretVal == 24); + std::allocator deallocer; + deallocer.destroy(this); + deallocer.deallocate(this, 1); + } + + private: + int _secretVal = 24; +}; + class TestWorker : public AsyncWorker { public: static void DoWork(const CallbackInfo& info) { @@ -15,7 +84,13 @@ class TestWorker : public AsyncWorker { Function cb = info[2].As(); Value data = info[3]; - TestWorker* worker = new TestWorker(cb, "TestResource", resource); + TestWorker* worker = nullptr; + if (resource == info.Env().Null()) { + worker = new TestWorker(cb, "TestResource"); + } else { + worker = new TestWorker(cb, "TestResource", resource); + } + worker->Receiver().Set("data", data); worker->_succeed = succeed; worker->Queue(); @@ -31,6 +106,8 @@ class TestWorker : public AsyncWorker { private: TestWorker(Function cb, const char* resource_name, const Object& resource) : AsyncWorker(cb, resource_name, resource) {} + TestWorker(Function cb, const char* resource_name) + : AsyncWorker(cb, resource_name) {} bool _succeed; }; @@ -72,12 +149,25 @@ class TestWorkerWithResult : public AsyncWorker { class TestWorkerNoCallback : public AsyncWorker { public: static Value DoWork(const CallbackInfo& info) { + bool succeed = info[0].As(); + + TestWorkerNoCallback* worker = new TestWorkerNoCallback(info.Env()); + worker->_succeed = succeed; + worker->Queue(); + return worker->_deferred.Promise(); + } + + static Value DoWorkWithAsyncRes(const CallbackInfo& info) { napi_env env = info.Env(); bool succeed = info[0].As(); Object resource = info[1].As(); - TestWorkerNoCallback* worker = - new TestWorkerNoCallback(env, "TestResource", resource); + TestWorkerNoCallback* worker = nullptr; + if (resource == info.Env().Null()) { + worker = new TestWorkerNoCallback(env, "TestResource"); + } else { + worker = new TestWorkerNoCallback(env, "TestResource", resource); + } worker->_succeed = succeed; worker->Queue(); return worker->_deferred.Promise(); @@ -91,6 +181,13 @@ class TestWorkerNoCallback : public AsyncWorker { } private: + TestWorkerNoCallback(Napi::Env env) + : AsyncWorker(env), _deferred(Napi::Promise::Deferred::New(env)) {} + + TestWorkerNoCallback(napi_env env, const char* resource_name) + : AsyncWorker(env, resource_name), + _deferred(Napi::Promise::Deferred::New(env)) {} + TestWorkerNoCallback(napi_env env, const char* resource_name, const Object& resource) @@ -222,7 +319,12 @@ class CancelWorker : public AsyncWorker { Object InitAsyncWorker(Env env) { Object exports = Object::New(env); + exports["doWorkRecv"] = Function::New(env, TestWorkerWithUserDefRecv::DoWork); + exports["doWithRecvAsyncRes"] = + Function::New(env, TestWorkerWithUserDefRecv::DoWorkWithAsyncRes); exports["doWork"] = Function::New(env, TestWorker::DoWork); + exports["doWorkAsyncResNoCallback"] = + Function::New(env, TestWorkerNoCallback::DoWorkWithAsyncRes); exports["doWorkNoCallback"] = Function::New(env, TestWorkerNoCallback::DoWork); exports["doWorkWithResult"] = @@ -231,5 +333,7 @@ Object InitAsyncWorker(Env env) { exports["expectCancelToFail"] = Function::New(env, FailCancelWorker::DoCancel); + exports["expectCustomAllocWorkerToDealloc"] = + Function::New(env, CustomAllocWorker::DoWork); return exports; } diff --git a/test/async_worker.js b/test/async_worker.js index 2f0274026..304a3247f 100644 --- a/test/async_worker.js +++ b/test/async_worker.js @@ -76,8 +76,20 @@ async function test (binding) { assert.equal(taskFailed, true, 'We expect task cancellation to fail'); if (!checkAsyncHooks()) { + binding.asyncworker.expectCustomAllocWorkerToDealloc(() => {}); + + await new Promise((resolve) => { + const obj = { data: 'test data' }; + binding.asyncworker.doWorkRecv(obj, function (e) { + assert.strictEqual(typeof e, 'undefined'); + assert.strictEqual(typeof this, 'object'); + assert.strictEqual(this.data, 'test data'); + resolve(); + }); + }); + await new Promise((resolve) => { - binding.asyncworker.doWork(true, {}, function (e) { + binding.asyncworker.doWork(true, null, function (e) { assert.strictEqual(typeof e, 'undefined'); assert.strictEqual(typeof this, 'object'); assert.strictEqual(this.data, 'test data'); @@ -109,6 +121,62 @@ async function test (binding) { return; } + { + const hooks = installAsyncHooksForTest(); + const triggerAsyncId = asyncHooks.executionAsyncId(); + await new Promise((resolve) => { + const recvObj = { data: 'test data' }; + binding.asyncworker.doWithRecvAsyncRes(recvObj, function (e) { + assert.strictEqual(typeof e, 'undefined'); + assert.strictEqual(typeof this, 'object'); + assert.strictEqual(this.data, 'test data'); + resolve(); + }, { foo: 'fooBar' }); + }); + + await hooks.then(actual => { + assert.deepStrictEqual(actual, [ + { + eventName: 'init', + type: 'TestResource', + triggerAsyncId: triggerAsyncId, + resource: { foo: 'fooBar' } + }, + { eventName: 'before' }, + { eventName: 'after' }, + { eventName: 'destroy' } + ]); + }).catch(common.mustNotCall()); + } + + { + const hooks = installAsyncHooksForTest(); + const triggerAsyncId = asyncHooks.executionAsyncId(); + await new Promise((resolve) => { + const recvObj = { data: 'test data' }; + binding.asyncworker.doWithRecvAsyncRes(recvObj, function (e) { + assert.strictEqual(typeof e, 'undefined'); + assert.strictEqual(typeof this, 'object'); + assert.strictEqual(this.data, 'test data'); + resolve(); + }, null); + }); + + await hooks.then(actual => { + assert.deepStrictEqual(actual, [ + { + eventName: 'init', + type: 'TestResource', + triggerAsyncId: triggerAsyncId, + resource: { } + }, + { eventName: 'before' }, + { eventName: 'after' }, + { eventName: 'destroy' } + ]); + }).catch(common.mustNotCall()); + } + { const hooks = installAsyncHooksForTest(); const triggerAsyncId = asyncHooks.executionAsyncId(); diff --git a/test/async_worker_nocallback.js b/test/async_worker_nocallback.js index 8e357772f..2f848c4e9 100644 --- a/test/async_worker_nocallback.js +++ b/test/async_worker_nocallback.js @@ -5,9 +5,15 @@ const common = require('./common'); module.exports = common.runTest(test); async function test (binding) { - await binding.asyncworker.doWorkNoCallback(true, {}) + await binding.asyncworker.doWorkAsyncResNoCallback(true, {}) .then(common.mustCall()).catch(common.mustNotCall()); - await binding.asyncworker.doWorkNoCallback(false, {}) + await binding.asyncworker.doWorkAsyncResNoCallback(false, {}) + .then(common.mustNotCall()).catch(common.mustCall()); + + await binding.asyncworker.doWorkNoCallback(false) + .then(common.mustNotCall()).catch(common.mustCall()); + + await binding.asyncworker.doWorkNoCallback(true) .then(common.mustNotCall()).catch(common.mustCall()); }