Skip to content

Commit 257a52f

Browse files
authored
test: Add test cased for failed task cancellations (#1214)
* test: Add test cased for failed task cancellations
1 parent 793268c commit 257a52f

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

test/async_worker.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include <chrono>
2+
#include <condition_variable>
3+
#include <mutex>
24
#include <thread>
35
#include "assert.h"
46
#include "napi.h"
@@ -117,6 +119,58 @@ class EchoWorker : public AsyncWorker {
117119
std::string echo;
118120
};
119121

122+
class FailCancelWorker : public AsyncWorker {
123+
private:
124+
bool taskIsRunning = false;
125+
std::mutex mu;
126+
std::condition_variable taskStartingCv;
127+
void NotifyJSThreadTaskHasStarted() {
128+
{
129+
std::lock_guard<std::mutex> lk(mu);
130+
taskIsRunning = true;
131+
taskStartingCv.notify_one();
132+
}
133+
}
134+
135+
public:
136+
FailCancelWorker(Function& cb) : AsyncWorker(cb) {}
137+
~FailCancelWorker() {}
138+
139+
void WaitForWorkerTaskToStart() {
140+
std::unique_lock<std::mutex> lk(mu);
141+
taskStartingCv.wait(lk, [this] { return taskIsRunning; });
142+
taskIsRunning = false;
143+
}
144+
145+
static void DoCancel(const CallbackInfo& info) {
146+
Function cb = info[0].As<Function>();
147+
148+
FailCancelWorker* cancelWorker = new FailCancelWorker(cb);
149+
cancelWorker->Queue();
150+
cancelWorker->WaitForWorkerTaskToStart();
151+
152+
#ifdef NAPI_CPP_EXCEPTIONS
153+
try {
154+
cancelWorker->Cancel();
155+
} catch (Napi::Error& e) {
156+
Napi::Error::New(info.Env(), "Unable to cancel async worker tasks")
157+
.ThrowAsJavaScriptException();
158+
}
159+
#else
160+
cancelWorker->Cancel();
161+
#endif
162+
}
163+
164+
void Execute() override {
165+
NotifyJSThreadTaskHasStarted();
166+
std::this_thread::sleep_for(std::chrono::seconds(1));
167+
}
168+
169+
void OnOK() override {}
170+
171+
void OnError(const Error&) override {}
172+
};
173+
120174
class CancelWorker : public AsyncWorker {
121175
public:
122176
CancelWorker(Function& cb) : AsyncWorker(cb) {}
@@ -174,5 +228,8 @@ Object InitAsyncWorker(Env env) {
174228
exports["doWorkWithResult"] =
175229
Function::New(env, TestWorkerWithResult::DoWork);
176230
exports["tryCancelQueuedWork"] = Function::New(env, CancelWorker::DoWork);
231+
232+
exports["expectCancelToFail"] =
233+
Function::New(env, FailCancelWorker::DoCancel);
177234
return exports;
178235
}

test/async_worker.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ async function test (binding) {
6666
const libUvThreadCount = Number(process.env.UV_THREADPOOL_SIZE || 4);
6767
binding.asyncworker.tryCancelQueuedWork(() => {}, 'echoString', libUvThreadCount);
6868

69+
let taskFailed = false;
70+
try {
71+
binding.asyncworker.expectCancelToFail(() => {});
72+
} catch (e) {
73+
taskFailed = true;
74+
}
75+
76+
assert.equal(taskFailed, true, 'We expect task cancellation to fail');
77+
6978
if (!checkAsyncHooks()) {
7079
await new Promise((resolve) => {
7180
binding.asyncworker.doWork(true, {}, function (e) {

0 commit comments

Comments
 (0)