Skip to content

Commit

Permalink
test: Add test case for canceling async worker tasks (#1202)
Browse files Browse the repository at this point in the history
* test: Add test case for canceling async worker tasks
  • Loading branch information
JckXia authored Sep 26, 2022
1 parent 1331856 commit 793268c
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
72 changes: 72 additions & 0 deletions test/async_worker.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <chrono>
#include <thread>
#include "assert.h"
#include "napi.h"

using namespace Napi;
Expand Down Expand Up @@ -95,12 +98,81 @@ class TestWorkerNoCallback : public AsyncWorker {
bool _succeed;
};

class EchoWorker : public AsyncWorker {
public:
EchoWorker(Function& cb, std::string& echo) : AsyncWorker(cb), echo(echo) {}
~EchoWorker() {}

void Execute() override {
// Simulate cpu heavy task
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}

void OnOK() override {
HandleScope scope(Env());
Callback().Call({Env().Null(), String::New(Env(), echo)});
}

private:
std::string echo;
};

class CancelWorker : public AsyncWorker {
public:
CancelWorker(Function& cb) : AsyncWorker(cb) {}
~CancelWorker() {}

static void DoWork(const CallbackInfo& info) {
Function cb = info[0].As<Function>();
std::string echo = info[1].As<String>();
int threadNum = info[2].As<Number>().Uint32Value();

for (int i = 0; i < threadNum; i++) {
AsyncWorker* worker = new EchoWorker(cb, echo);
worker->Queue();
assert(worker->Env() == info.Env());
}

AsyncWorker* cancelWorker = new CancelWorker(cb);
cancelWorker->Queue();

#ifdef NAPI_CPP_EXCEPTIONS
try {
cancelWorker->Cancel();
} catch (Napi::Error& e) {
Napi::Error::New(info.Env(), "Unable to cancel async worker tasks")
.ThrowAsJavaScriptException();
}
#else
cancelWorker->Cancel();
#endif
}

void Execute() override {
// Simulate cpu heavy task
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void OnOK() override {
Napi::Error::New(this->Env(),
"OnOk should not be invoked on successful cancellation")
.ThrowAsJavaScriptException();
}

void OnError(const Error&) override {
Napi::Error::New(this->Env(),
"OnError should not be invoked on successful cancellation")
.ThrowAsJavaScriptException();
}
};

Object InitAsyncWorker(Env env) {
Object exports = Object::New(env);
exports["doWork"] = Function::New(env, TestWorker::DoWork);
exports["doWorkNoCallback"] =
Function::New(env, TestWorkerNoCallback::DoWork);
exports["doWorkWithResult"] =
Function::New(env, TestWorkerWithResult::DoWork);
exports["tryCancelQueuedWork"] = Function::New(env, CancelWorker::DoWork);
return exports;
}
3 changes: 3 additions & 0 deletions test/async_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ function installAsyncHooksForTest () {
}

async function test (binding) {
const libUvThreadCount = Number(process.env.UV_THREADPOOL_SIZE || 4);
binding.asyncworker.tryCancelQueuedWork(() => {}, 'echoString', libUvThreadCount);

if (!checkAsyncHooks()) {
await new Promise((resolve) => {
binding.asyncworker.doWork(true, {}, function (e) {
Expand Down

0 comments on commit 793268c

Please sign in to comment.