1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http:// www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "test.h"
17
18 #include <chrono>
19 #include <thread>
20 #include <uv.h>
21
22 #include "event_runner.h"
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "securec.h"
26 #include "utils/log.h"
27
28 struct CallJsCbData_t {
29 int32_t id = 0;
30 bool secondaryThread = false;
31 napi_threadsafe_function_call_mode blockOnFull = napi_tsfn_nonblocking;
32 };
33
34 struct FinalCbData_t {
35 int32_t id = 0;
36 };
37
38 struct CallbackData {
39 napi_threadsafe_function tsfn;
40 napi_async_work work;
41 napi_task_priority priority;
42 };
43
44 static constexpr int32_t SEND_DATA_TEST = 11;
45 static constexpr int32_t CALL_JS_CB_DATA_TEST_ID = 101;
46 static constexpr int32_t FINAL_CB_DATA_TEST_ID = 1001;
47 static constexpr int32_t SEND_DATAS_LENGTH = 10;
48 static constexpr int32_t THREAD_COUNT = 2;
49 static constexpr int32_t THREAD_COUNT_FOUR = 4;
50 static constexpr int32_t MAX_QUEUE_SIZE = 3;
51 static constexpr int32_t SUCCESS_COUNT_JS_FOUR = 4;
52 static constexpr int32_t CALL_THREAD_SAFE_SLEEP = 2; // 2s
53 static constexpr int32_t FIRST_TASK_SLEEP = 4; // 4s
54 static constexpr int32_t INVALID_NAPI_THREAD_SAFE_PRIORITY = -1;
55 static constexpr int32_t ADD_FIRST_NUMBER = 1;
56 static constexpr int32_t ADD_SECOND_NUMBER = 2;
57 static constexpr int32_t ADD_SUMMARY_RESULT = 3;
58 static constexpr int32_t ARGS_SIZE = 2;
59 static constexpr int32_t FIRST_RECEIVER = 1;
60 static constexpr int32_t SECOND_RECEIVER = 2;
61 static constexpr int32_t THIRD_RECEIVER = 3;
62 static constexpr int32_t FOURTH_RECEIVER = 4;
63 static constexpr int32_t FIFTH_RECEIVER = 5;
64 static constexpr int32_t DATA_LENGTH = 40;
65 static constexpr int32_t THREAD_SIZE = 5;
66 static constexpr int32_t FIRST_THREAD_INDEX = 0;
67 static constexpr int32_t SECOND_THREAD_INDEX = 1;
68 static constexpr int32_t THIRD_THREAD_INDEX = 2;
69 static constexpr int32_t FOURTH_THREAD_INDEX = 3;
70 static constexpr int32_t FIFTH_THREAD_INDEX = 4;
71
72 static pid_t g_mainTid = 0;
73 static CallJsCbData_t g_jsData;
74 static CallJsCbData_t g_jsDataInternal;
75 static FinalCbData_t g_finalData;
76 static int32_t g_sendData = 0;
77 static uv_thread_t g_uvThread;
78 static uv_thread_t g_uvThreadTest5;
79 static uv_thread_t g_uvThreadTest6;
80 static uv_thread_t g_uvThreadTest7;
81 static uv_thread_t g_uvThreadSecondary;
82 static uv_thread_t g_uvTheads2;
83 static uv_thread_t g_uvTheads3;
84 static int32_t g_sendDatas[SEND_DATAS_LENGTH];
85 static int32_t g_callSuccessCount = 0;
86 static int32_t g_callSuccessCountJS = 0;
87 static int32_t g_callSuccessCountJSFour = 0;
88 static int32_t g_callDepth = 4;
89 bool acquireFlag = false;
90 static int32_t g_receiveCnt = 0;
91 static bool g_isTailA = false;
92 static bool g_isTailB = false;
93
TsFuncCallJs(napi_env env, napi_value tsfn_cb, void* context, void* data)94 static void TsFuncCallJs(napi_env env, napi_value tsfn_cb, void* context, void* data)
95 {
96 HILOG_INFO("TsFuncCallJs called");
97
98 EXPECT_EQ(gettid(), g_mainTid);
99
100 // expect context equal
101 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
102
103 // expect data equal
104 int* pData = (int32_t*)data;
105 EXPECT_EQ((*pData), SEND_DATA_TEST);
106 }
107
TsFuncCallJsWithNewCall(napi_env env, napi_value tsfn_cb, void* context, void* data)108 static void TsFuncCallJsWithNewCall(napi_env env, napi_value tsfn_cb, void* context, void* data)
109 {
110 HILOG_INFO("TsFuncCallJsWithNewCall called");
111 EXPECT_EQ(gettid(), g_mainTid);
112
113 // expect context equal
114 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
115
116 napi_threadsafe_function tsFunc = (napi_threadsafe_function)data;
117
118 if (g_callDepth > 0) {
119 g_callDepth--;
120 auto status = napi_call_threadsafe_function(tsFunc, data, napi_tsfn_nonblocking);
121 EXPECT_EQ(status, napi_ok);
122 }
123 if (g_callDepth == 0) {
124 auto status = napi_release_threadsafe_function(tsFunc, napi_tsfn_release);
125 EXPECT_EQ(status, napi_ok);
126 }
127 }
128
TsFuncCallJsTwo(napi_env env, napi_value tsfn_cb, void* context, void* data)129 static void TsFuncCallJsTwo(napi_env env, napi_value tsfn_cb, void* context, void* data)
130 {
131 HILOG_INFO("TsFuncCallJsTwo called");
132 TsFuncCallJs(env, tsfn_cb, context, data);
133 g_callSuccessCountJS++;
134 }
TsFuncCallJsFour(napi_env env, napi_value tsfn_cb, void* context, void* data)135 static void TsFuncCallJsFour(napi_env env, napi_value tsfn_cb, void* context, void* data)
136 {
137 HILOG_INFO("TsFuncCallJsFour called");
138
139 TsFuncCallJs(env, tsfn_cb, context, data);
140 g_callSuccessCountJSFour++;
141 }
TsFuncCallJsMulti(napi_env env, napi_value tsfn_cb, void* context, void* data)142 static void TsFuncCallJsMulti(napi_env env,
143 napi_value tsfn_cb,
144 void* context,
145 void* data)
146 {
147 HILOG_INFO("TsFuncCallJsMulti called");
148
149 EXPECT_EQ(gettid(), g_mainTid);
150
151 // expect context equal
152 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
153
154 int* pData = ((int32_t*)data);
155
156 HILOG_INFO("TsFuncCallJsMulti data %d", (*pData));
157 }
158
TsFuncFinal(napi_env env, void* finalizeData, void* hint)159 static void TsFuncFinal(napi_env env, void* finalizeData, void* hint)
160 {
161 HILOG_INFO("TsFuncFinal called");
162
163 // expect thread id equal
164 EXPECT_EQ(gettid(), g_mainTid);
165
166 // wait data source thread
167 uv_thread_join(&g_uvThread);
168
169 // expect context equal
170 EXPECT_EQ(((CallJsCbData_t*)hint)->id, CALL_JS_CB_DATA_TEST_ID);
171
172 // expect finalize data equal
173 EXPECT_EQ(((FinalCbData_t*)finalizeData)->id, FINAL_CB_DATA_TEST_ID);
174 }
TsFuncFinalTest5(napi_env env, void* finalizeData, void* hint)175 static void TsFuncFinalTest5(napi_env env, void* finalizeData, void* hint)
176 {
177 HILOG_INFO("TsFuncFinalTest5 called");
178
179 // expect thread id equal
180 EXPECT_EQ(gettid(), g_mainTid);
181
182 // wait data source thread
183 uv_thread_join(&g_uvThreadTest5);
184
185 // expect context equal
186 EXPECT_EQ(((CallJsCbData_t*)hint)->id, CALL_JS_CB_DATA_TEST_ID);
187
188 // expect finalize data equal
189 EXPECT_EQ(((FinalCbData_t*)finalizeData)->id, FINAL_CB_DATA_TEST_ID);
190 }
TsFuncFinalTotal(napi_env env, void* finalizeData, void* hint)191 static void TsFuncFinalTotal(napi_env env, void* finalizeData, void* hint)
192 {
193 HILOG_INFO("TsFuncFinalTotal called");
194 uv_thread_join(&g_uvThreadTest6);
195 // when add thread,repair g_callSuccessCountJS eq SUCCESS_COUNT_JS_TWO
196 EXPECT_EQ(g_callSuccessCountJS, SUCCESS_COUNT_JS_FOUR);
197 HILOG_INFO("TsFuncFinalTotal end");
198 }
TsFuncFinalTotalFour(napi_env env, void* finalizeData, void* hint)199 static void TsFuncFinalTotalFour(napi_env env, void* finalizeData, void* hint)
200 {
201 HILOG_INFO("TsFuncFinalTotalFour called");
202 uv_thread_join(&g_uvThreadTest7);
203 EXPECT_EQ(g_callSuccessCountJSFour, SUCCESS_COUNT_JS_FOUR);
204 HILOG_INFO("TsFuncFinalTotalFour end");
205 }
TsFuncFinalCallback(napi_env env, void* finalizeData, void* hint)206 static void TsFuncFinalCallback(napi_env env, void* finalizeData, void* hint)
207 {
208 HILOG_INFO("TsFuncFinalCallback called");
209 EXPECT_EQ(g_callSuccessCountJSFour, SUCCESS_COUNT_JS_FOUR);
210 HILOG_INFO("TsFuncFinalCallback end");
211 }
212
TsFuncFinalJoinThread(napi_env env, void* data, void* hint)213 static void TsFuncFinalJoinThread(napi_env env, void* data, void* hint)
214 {
215 HILOG_INFO("TsFuncFinalJoinThread called");
216
217 uv_thread_t *uvThread = reinterpret_cast<uv_thread_t*>(data);
218 CallJsCbData_t *jsData = reinterpret_cast<CallJsCbData_t*>(hint);
219
220 uv_thread_join(uvThread);
221
222 if (jsData->secondaryThread) {
223 uv_thread_join(&g_uvThreadSecondary);
224 }
225 }
226
TsFuncSecondaryThread(void* data)227 static void TsFuncSecondaryThread(void* data)
228 {
229 HILOG_INFO("TsFuncSecondaryThread called");
230
231 // expect thread id not equal
232 EXPECT_NE(gettid(), g_mainTid);
233
234 napi_threadsafe_function func = (napi_threadsafe_function)data;
235
236 auto status = napi_release_threadsafe_function(func, napi_tsfn_release);
237 EXPECT_EQ(status, napi_ok);
238 }
239
TsFuncDataSourceThread(void* data)240 static void TsFuncDataSourceThread(void* data)
241 {
242 HILOG_INFO("TsFuncDataSourceThread called");
243
244 // expect thread id not equal
245 EXPECT_NE(gettid(), g_mainTid);
246
247 napi_threadsafe_function func = (napi_threadsafe_function)data;
248 napi_threadsafe_function_call_mode blockMode = napi_tsfn_nonblocking;
249 void* context = nullptr;
250
251 auto status = napi_get_threadsafe_function_context(func, &context);
252 EXPECT_EQ(status, napi_ok);
253
254 // expect context equal
255 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
256
257 // set send data
258 g_sendData = SEND_DATA_TEST;
259
260 // As main thread has set initial_thread_count to 1 and only this one secondary thread,
261 // so no need to call `napi_acquire_threadsafe_function()`.
262 status = napi_call_threadsafe_function(func, &g_sendData, blockMode);
263 EXPECT_EQ(status, napi_ok);
264
265 status = napi_release_threadsafe_function(func, napi_tsfn_release);
266 EXPECT_EQ(status, napi_ok);
267 }
TsFuncDataSourceThreadAbort(void* data)268 static void TsFuncDataSourceThreadAbort(void* data)
269 {
270 HILOG_INFO("TsFuncDataSourceThreadAbort called");
271
272 // expect thread id not equal
273 EXPECT_NE(gettid(), g_mainTid);
274
275 napi_threadsafe_function func = (napi_threadsafe_function)data;
276 napi_threadsafe_function_call_mode blockMode = napi_tsfn_nonblocking;
277 void* context = nullptr;
278
279 auto status = napi_get_threadsafe_function_context(func, &context);
280 EXPECT_EQ(status, napi_ok);
281
282 // expect context equal
283 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
284
285 // set send data
286 g_sendData = SEND_DATA_TEST;
287
288 status = napi_call_threadsafe_function(func, &g_sendData, blockMode);
289 EXPECT_EQ(status, napi_closing);
290 }
291
TsFuncDataSourceThreadCountTotal(void* data)292 static void TsFuncDataSourceThreadCountTotal(void* data)
293 {
294 HILOG_INFO("TsFuncDataSourceThreadCountTotal called");
295
296 // expect thread id not equal
297 EXPECT_NE(gettid(), g_mainTid);
298
299 napi_threadsafe_function func = (napi_threadsafe_function)data;
300 napi_threadsafe_function_call_mode blockMode = napi_tsfn_nonblocking;
301 void* context = nullptr;
302
303 auto status = napi_get_threadsafe_function_context(func, &context);
304 EXPECT_EQ(status, napi_ok);
305
306 // expect context equal
307 EXPECT_EQ(((CallJsCbData_t*)context)->id, CALL_JS_CB_DATA_TEST_ID);
308 // set send data
309 g_sendData = SEND_DATA_TEST;
310 if (acquireFlag) {
311 std::cout<<"acquireFlag is true"<<std::endl;
312 status = napi_acquire_threadsafe_function(func);
313 EXPECT_EQ(status, napi_ok);
314 status = napi_call_threadsafe_function(func, &g_sendData, blockMode);
315 if (status == napi_ok) {
316 g_callSuccessCount++;
317 }
318 status = napi_release_threadsafe_function(func, napi_tsfn_release);
319 } else {
320 status = napi_call_threadsafe_function(func, &g_sendData, blockMode);
321 if (status == napi_ok) {
322 g_callSuccessCount++;
323 }
324 }
325 status = napi_release_threadsafe_function(func, napi_tsfn_release);
326 }
327
TsFuncDataSourceThreadMulti(void* data)328 static void TsFuncDataSourceThreadMulti(void* data)
329 {
330 HILOG_INFO("TsFuncDataSourceThreadMulti called");
331
332 // expect thread id not equal
333 EXPECT_NE(gettid(), g_mainTid);
334
335 napi_threadsafe_function func = (napi_threadsafe_function)data;
336 void* context = nullptr;
337
338 auto status = napi_get_threadsafe_function_context(func, &context);
339 EXPECT_EQ(status, napi_ok);
340 CallJsCbData_t* jsData = nullptr;
341 jsData = (CallJsCbData_t*)context;
342
343 if (jsData->secondaryThread) {
344 status = napi_acquire_threadsafe_function(func);
345 EXPECT_EQ(status, napi_ok);
346
347 if (uv_thread_create(&g_uvThreadSecondary, TsFuncSecondaryThread, func) != 0) {
348 HILOG_ERROR("Failed to create uv thread!");
349 }
350 }
351
352 bool queueClosing = false;
353 bool queueFull = false;
354 int32_t index = 0;
355 for (index = SEND_DATAS_LENGTH - 1; index > -1 && !queueClosing; index--) {
356 g_sendDatas[index] = index;
357 status = napi_call_threadsafe_function(func, &g_sendDatas[index], jsData->blockOnFull);
358 HILOG_INFO("napi_call_threadsafe_function index %d status %d", index, status);
359
360 switch (status) {
361 case napi_queue_full:
362 queueFull = true;
363 index++;
364 [[fallthrough]];
365 case napi_ok:
366 continue;
367 case napi_closing:
368 queueClosing = true;
369 break;
370 default:
371 HILOG_ERROR("Failed to call napi_call_threadsafe_function!");
372 }
373 }
374
375 if (!queueClosing && (napi_release_threadsafe_function(func, napi_tsfn_release) != napi_ok)) {
376 HILOG_ERROR("Failed to call napi_release_threadsafe_function!");
377 }
378 }
379
TsFuncThreadInternal(napi_env env, napi_threadsafe_function_call_js cb, uv_thread_t& uvThread, bool secondary, bool block)380 static void TsFuncThreadInternal(napi_env env,
381 napi_threadsafe_function_call_js cb,
382 uv_thread_t& uvThread,
383 bool secondary,
384 bool block)
385 {
386 HILOG_INFO("TsFuncThreadInternal start secondary %d block %d", secondary, block);
387
388 napi_threadsafe_function tsFunc = nullptr;
389 napi_value resourceName = 0;
390
391 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
392 g_mainTid = gettid();
393
394 g_jsDataInternal.id = CALL_JS_CB_DATA_TEST_ID;
395 g_jsDataInternal.secondaryThread = (secondary ? true : false);
396 g_jsDataInternal.blockOnFull = (block ? napi_tsfn_blocking : napi_tsfn_nonblocking);
397
398 auto status = napi_create_threadsafe_function(env,
399 nullptr,
400 nullptr,
401 resourceName,
402 MAX_QUEUE_SIZE,
403 THREAD_COUNT,
404 &uvThread,
405 TsFuncFinalJoinThread,
406 &g_jsDataInternal,
407 cb,
408 &tsFunc);
409 EXPECT_EQ(status, napi_ok);
410
411 if (uv_thread_create(&uvThread, TsFuncDataSourceThreadMulti, tsFunc) != 0) {
412 HILOG_ERROR("Failed to create uv thread!");
413 }
414
415 HILOG_INFO("TsFuncThreadInternal end");
416 }
417
JsCallback(napi_env env, napi_callback_info info)418 static napi_value JsCallback(napi_env env, napi_callback_info info)
419 {
420 size_t agrc = ARGS_SIZE;
421 napi_value argv[ARGS_SIZE] = { nullptr };
422 napi_get_cb_info(env, info, &agrc, argv, nullptr, nullptr);
423
424 int32_t number1 = 0;
425 napi_get_value_int32(env, argv[0], &number1);
426
427 int32_t number2 = 0;
428 napi_get_value_int32(env, argv[1], &number2);
429
430 napi_value result = nullptr;
431 napi_create_int32(env, number1 + number2, &result);
432 return result;
433 }
434
CallJsCallback(napi_env env, napi_value jsCb)435 static void CallJsCallback(napi_env env, napi_value jsCb)
436 {
437 napi_value undefined;
438 napi_get_undefined(env, &undefined);
439 napi_value numberOne = nullptr;
440 napi_create_int32(env, ADD_FIRST_NUMBER, &numberOne);
441 napi_value numberTwo = nullptr;
442 napi_create_int32(env, ADD_SECOND_NUMBER, &numberTwo);
443 napi_value argv[ARGS_SIZE] = { numberOne, numberTwo };
444
445 napi_value result = nullptr;
446 napi_call_function(env, undefined, jsCb, ARGS_SIZE, argv, &result);
447
448 int32_t res = 0;
449 napi_get_value_int32(env, result, &res);
450 EXPECT_EQ(res, ADD_SUMMARY_RESULT);
451 }
452
StopCurrentRunner()453 static void StopCurrentRunner()
454 {
455 auto runner = OHOS::AppExecFwk::EventRunner::Current();
456 if (runner != nullptr) {
457 HILOG_INFO("Stop the current runner!");
458 runner->Stop();
459 }
460 }
461
CallJs(napi_env env, napi_value jsCb, void *context, void *data)462 static void CallJs(napi_env env, napi_value jsCb, void *context, void *data)
463 {
464 EXPECT_NE(env, nullptr);
465
466 g_receiveCnt++;
467 if (g_receiveCnt == FIRST_RECEIVER) {
468 std::this_thread::sleep_for(std::chrono::seconds(FIRST_TASK_SLEEP));
469 return;
470 }
471 // check data string
472 char *testData = reinterpret_cast<char *>(data);
473 EXPECT_NE(testData, nullptr) << "testData is nullptr";
474 int32_t ret = 0;
475 if (g_receiveCnt == SECOND_RECEIVER) {
476 if (!g_isTailB) {
477 ret = strcmp(testData, "hello world from B");
478 } else {
479 ret = strcmp(testData, "hello world from A");
480 }
481 }
482 if (g_receiveCnt == THIRD_RECEIVER) {
483 if (!g_isTailB) {
484 ret = strcmp(testData, "hello world from A");
485 } else {
486 ret = strcmp(testData, "hello world from B");
487 }
488 }
489 EXPECT_EQ(ret, 0);
490
491 CallJsCallback(env, jsCb);
492 if (g_receiveCnt == THIRD_RECEIVER) {
493 StopCurrentRunner();
494 }
495 }
496
CallJsWithDiffPriority(napi_env env, napi_value jsCb, void *context, void *data)497 static void CallJsWithDiffPriority(napi_env env, napi_value jsCb, void *context, void *data)
498 {
499 EXPECT_NE(env, nullptr);
500
501 g_receiveCnt++;
502 if (g_receiveCnt == FIRST_RECEIVER) {
503 std::this_thread::sleep_for(std::chrono::seconds(FIRST_TASK_SLEEP));
504 return;
505 }
506 // check data string
507 char *testData = reinterpret_cast<char *>(data);
508 EXPECT_NE(testData, nullptr) << "testData is nullptr";
509 int32_t ret = 0;
510 if (g_receiveCnt == SECOND_RECEIVER) {
511 ret = strcmp(testData, "hello world from A");
512 } else if (g_receiveCnt == THIRD_RECEIVER) {
513 ret = strcmp(testData, "hello world from B");
514 } else if (g_receiveCnt == FOURTH_RECEIVER) {
515 ret = strcmp(testData, "hello world from C");
516 } else if (g_receiveCnt == FIFTH_RECEIVER) {
517 ret = strcmp(testData, "hello world from D");
518 }
519 EXPECT_EQ(ret, 0);
520
521 CallJsCallback(env, jsCb);
522 if (g_receiveCnt == FIFTH_RECEIVER) {
523 StopCurrentRunner();
524 }
525 }
526
527 class UnitLoopHandler : public OHOS::AppExecFwk::FileDescriptorListener,
528 public std::enable_shared_from_this<UnitLoopHandler> {
529 public:
UnitLoopHandler(uv_loop_t* uvLoop)530 explicit UnitLoopHandler(uv_loop_t* uvLoop) : uvLoop_(uvLoop) {}
531 void OnReadable(int32_t) override { uv_run(uvLoop_, UV_RUN_NOWAIT); }
532 void OnWritable(int32_t) override { uv_run(uvLoop_, UV_RUN_NOWAIT); }
533
534 private:
535 uv_loop_t* uvLoop_ = nullptr;
536 };
537
538 class NapiThreadsafeTest : public NativeEngineTest {
539 public:
SetUpTestCase()540 static void SetUpTestCase()
541 {
542 GTEST_LOG_(INFO) << "NapiThreadsafeTest SetUpTestCase";
543 }
544
TearDownTestCase()545 static void TearDownTestCase()
546 {
547 GTEST_LOG_(INFO) << "NapiThreadsafeTest TearDownTestCase";
548 }
549
550 void SetUp() override { AttachEventHandler(); }
551 void TearDown() override {}
552
553 void CallThreadSafeWithSamePriorityTest(napi_task_priority priority);
554 void CallThreadSafeWithDiffPriorityTest();
555 void CallThreadSafeWithDiffPriorityMultipleThreadTest();
556 void AttachEventHandler();
557 };
558
AttachEventHandler()559 void NapiThreadsafeTest::AttachEventHandler()
560 {
561 if (eventHandler_ != nullptr) {
562 return;
563 }
564 auto uvLoop = engine_->GetUVLoop();
565 auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
566 EXPECT_GE(fd, 0);
567 uv_run(uvLoop, UV_RUN_NOWAIT);
568 auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
569 EXPECT_NE(runner, nullptr);
570 eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
571 EXPECT_NE(eventHandler_, nullptr);
572 uint32_t events = OHOS::AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT | OHOS::AppExecFwk::FILE_DESCRIPTOR_OUTPUT_EVENT;
573 eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared<UnitLoopHandler>(uvLoop), "uvLoopTask");
574 HILOG_INFO("AttachEventHandler is completed!");
575 }
576
CallThreadSafeFunc(napi_threadsafe_function tsfn, napi_task_priority priority)577 static void CallThreadSafeFunc(napi_threadsafe_function tsfn, napi_task_priority priority)
578 {
579 char *testData = (char *)malloc(DATA_LENGTH);
580 if (testData == nullptr) {
581 return;
582 }
583 memset_s(testData, DATA_LENGTH, 0, DATA_LENGTH);
584 if (priority == napi_priority_immediate) {
585 strcpy_s(testData, DATA_LENGTH, "hello world from A");
586 } else if (priority == napi_priority_high) {
587 strcpy_s(testData, DATA_LENGTH, "hello world from B");
588 } else if (priority == napi_priority_low) {
589 strcpy_s(testData, DATA_LENGTH, "hello world from C");
590 } else if (priority == napi_priority_idle) {
591 strcpy_s(testData, DATA_LENGTH, "hello world from D");
592 }
593 auto status =
594 napi_call_threadsafe_function_with_priority(tsfn, testData, priority, true);
595 EXPECT_EQ(status, napi_ok);
596 }
597
CallThreadSafeWithSamePriorityTest(napi_task_priority priority)598 void NapiThreadsafeTest::CallThreadSafeWithSamePriorityTest(napi_task_priority priority)
599 {
600 napi_env env = (napi_env)engine_;
601 napi_value resourceName = 0;
602 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
603 CallbackData *callbackData = new CallbackData();
604 callbackData->priority = priority;
605 napi_value testFunc = nullptr;
606 napi_create_function(env, "jsCallback", NAPI_AUTO_LENGTH, JsCallback, nullptr, &testFunc);
607
608 auto status = napi_create_threadsafe_function(env, testFunc, nullptr, resourceName,
609 0, 1, callbackData, nullptr, callbackData, CallJs, &callbackData->tsfn);
610 EXPECT_EQ(status, napi_ok);
611
612 g_receiveCnt = 0;
613 napi_create_async_work(
614 env, nullptr, resourceName, [](napi_env env, void* data) {
615 CallbackData* callbackData = (CallbackData*)data;
616 char *testDataA = (char *)malloc(DATA_LENGTH);
617 memset_s(testDataA, DATA_LENGTH, 0, DATA_LENGTH);
618 strcpy_s(testDataA, DATA_LENGTH, "hello world from A");
619
620 char *testDataB = (char *)malloc(DATA_LENGTH);
621 memset_s(testDataB, DATA_LENGTH, 0, DATA_LENGTH);
622 strcpy_s(testDataB, DATA_LENGTH, "hello world from B");
623 // first call function to post a sleep task, then the next execution from event queue which
624 // contains two tasks.
625 auto status =
626 napi_call_threadsafe_function_with_priority(callbackData->tsfn, testDataA, napi_priority_immediate,
627 true);
628 EXPECT_EQ(status, napi_ok);
629 std::this_thread::sleep_for(std::chrono::seconds(CALL_THREAD_SAFE_SLEEP));
630 status = napi_call_threadsafe_function_with_priority(callbackData->tsfn, testDataA,
631 callbackData->priority, g_isTailA);
632 EXPECT_EQ(status, napi_ok);
633 status = napi_call_threadsafe_function_with_priority(callbackData->tsfn, testDataB,
634 callbackData->priority, g_isTailB);
635 EXPECT_EQ(status, napi_ok);
636 },
637 [](napi_env env, napi_status status, void* data) {
638 CallbackData* callbackData = (CallbackData*)data;
639 napi_delete_async_work(env, callbackData->work);
640 auto status1 = napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
641 EXPECT_EQ(status1, napi_ok);
642 delete callbackData;
643 },
644 callbackData, &callbackData->work);
645 napi_queue_async_work(env, callbackData->work);
646 }
647
CallThreadSafeWithDiffPriorityTest()648 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityTest()
649 {
650 napi_env env = (napi_env)engine_;
651 napi_value resourceName = 0;
652 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
653 CallbackData *callbackData = new CallbackData();
654 napi_value testFunc = nullptr;
655 napi_create_function(env, "jsCallback", NAPI_AUTO_LENGTH, JsCallback, nullptr, &testFunc);
656
657 auto status = napi_create_threadsafe_function(env, testFunc, nullptr, resourceName,
658 0, 1, callbackData, nullptr, callbackData, CallJsWithDiffPriority, &callbackData->tsfn);
659 EXPECT_EQ(status, napi_ok);
660
661 g_receiveCnt = 0;
662 napi_create_async_work(
663 env, nullptr, resourceName, [](napi_env env, void* data) {
664 CallbackData* callbackData = (CallbackData*)data;
665 // first call function to post a sleep task, then the next execution from event queue which
666 // contains four different priority tasks.
667 auto status =
668 napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate,
669 true);
670 EXPECT_EQ(status, napi_ok);
671 std::this_thread::sleep_for(std::chrono::seconds(CALL_THREAD_SAFE_SLEEP));
672 CallThreadSafeFunc(callbackData->tsfn, napi_priority_immediate);
673 CallThreadSafeFunc(callbackData->tsfn, napi_priority_high);
674 CallThreadSafeFunc(callbackData->tsfn, napi_priority_low);
675 CallThreadSafeFunc(callbackData->tsfn, napi_priority_idle);
676 },
677 [](napi_env env, napi_status status, void* data) {
678 CallbackData* callbackData = (CallbackData*)data;
679 napi_delete_async_work(env, callbackData->work);
680 auto status1 = napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
681 EXPECT_EQ(status1, napi_ok);
682 delete callbackData;
683 },
684 callbackData, &callbackData->work);
685 napi_queue_async_work(env, callbackData->work);
686 }
687
CallThreadSafeWithDiffPriorityMultipleThreadTest()688 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityMultipleThreadTest()
689 {
690 napi_env env = (napi_env)engine_;
691 napi_value resourceName = 0;
692 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
693 CallbackData *callbackData = new CallbackData();
694 napi_value testFunc = nullptr;
695 napi_create_function(env, "jsCallback", NAPI_AUTO_LENGTH, JsCallback, nullptr, &testFunc);
696
697 auto status = napi_create_threadsafe_function(env, testFunc, nullptr, resourceName,
698 0, 1, callbackData, nullptr, callbackData, CallJsWithDiffPriority, &callbackData->tsfn);
699 EXPECT_EQ(status, napi_ok);
700
701 g_receiveCnt = 0;
702 auto runFunc = [callbackData](const napi_env &env, int32_t threadIndex) {
703 if (threadIndex == FIRST_THREAD_INDEX) {
704 auto status =
705 napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate,
706 true);
707 EXPECT_EQ(status, napi_ok);
708 } else if (threadIndex == SECOND_THREAD_INDEX) {
709 CallThreadSafeFunc(callbackData->tsfn, napi_priority_immediate);
710 } else if (threadIndex == THIRD_THREAD_INDEX) {
711 CallThreadSafeFunc(callbackData->tsfn, napi_priority_high);
712 } else if (threadIndex == FOURTH_THREAD_INDEX) {
713 CallThreadSafeFunc(callbackData->tsfn, napi_priority_low);
714 } else if (threadIndex == FIFTH_THREAD_INDEX) {
715 CallThreadSafeFunc(callbackData->tsfn, napi_priority_idle);
716 }
717 };
718 std::thread runFirstThread = std::thread(runFunc, std::ref(env), 0);
719 runFirstThread.detach();
720 std::this_thread::sleep_for(std::chrono::seconds(CALL_THREAD_SAFE_SLEEP));
721 for (int32_t index = 1; index < THREAD_SIZE; ++index) {
722 std::thread runThread = std::thread(runFunc, std::ref(env), index);
723 runThread.detach();
724 }
725 }
726
727 /**
728 * @tc.name: ThreadsafeTest001
729 * @tc.desc: Test LoadModule Func.
730 * @tc.type: FUNC
731 * @tc.require: I5K6KF
732 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest001, testing::ext::TestSize.Level1)733 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest001, testing::ext::TestSize.Level1)
734 {
735 HILOG_INFO("Threadsafe_Test_0100 start");
736 napi_env env = (napi_env)engine_;
737 napi_threadsafe_function tsFunc = nullptr;
738 napi_value resourceName = 0;
739
740 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
741 g_mainTid = gettid();
742 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
743 g_finalData.id = FINAL_CB_DATA_TEST_ID;
744
745 auto status = napi_create_threadsafe_function(env,
746 nullptr,
747 nullptr,
748 resourceName,
749 0,
750 1,
751 &g_finalData,
752 TsFuncFinal,
753 &g_jsData,
754 TsFuncCallJs,
755 &tsFunc);
756 EXPECT_EQ(status, napi_ok);
757
758 if (uv_thread_create(&g_uvThread, TsFuncDataSourceThread, tsFunc) != 0) {
759 HILOG_ERROR("Failed to create uv thread!");
760 }
761
762 HILOG_INFO("Threadsafe_Test_0100 end");
763 }
764
765 /**
766 * @tc.name: ThreadsafeTest002
767 * @tc.desc: Test LoadModule Func.
768 * @tc.type: FUNC
769 * @tc.require: I5K6KF
770 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest002, testing::ext::TestSize.Level1)771 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest002, testing::ext::TestSize.Level1)
772 {
773 HILOG_INFO("Threadsafe_Test_0200 start");
774
775 // start secondary thread, block on full
776 TsFuncThreadInternal((napi_env)engine_, TsFuncCallJsMulti, g_uvTheads2, true, true);
777
778 HILOG_INFO("Threadsafe_Test_0200 end");
779 }
780
781 /**
782 * @tc.name: ThreadsafeTest003
783 * @tc.desc: Test threadsafe Func, no js.
784 * @tc.type: FUNC
785 * @tc.require: I5K6KF
786 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest003, testing::ext::TestSize.Level1)787 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest003, testing::ext::TestSize.Level1)
788 {
789 HILOG_INFO("Threadsafe_Test_0300 start");
790
791 // secondary thread, not block
792 TsFuncThreadInternal((napi_env)engine_, TsFuncCallJsMulti, g_uvTheads3, false, false);
793
794 HILOG_INFO("Threadsafe_Test_0300 end");
795 }
796
797 /**
798 * @tc.name: ThreadsafeTest004
799 * @tc.desc: Test napi_release_threadsafe_function, napi_tsfn_abort.
800 * @tc.type: FUNC
801 * @tc.require: I5K6KF
802 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest004, testing::ext::TestSize.Level1)803 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest004, testing::ext::TestSize.Level1)
804 {
805 HILOG_INFO("Threadsafe_Test_0400 start");
806 napi_env env = (napi_env)engine_;
807 napi_threadsafe_function tsFunc = nullptr;
808 napi_value resourceName = 0;
809
810 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
811 g_mainTid = gettid();
812 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
813 g_finalData.id = FINAL_CB_DATA_TEST_ID;
814
815 auto status = napi_create_threadsafe_function(env,
816 nullptr,
817 nullptr,
818 resourceName,
819 0,
820 10,
821 &g_finalData,
822 TsFuncFinalTest5,
823 &g_jsData,
824 TsFuncCallJs,
825 &tsFunc);
826 EXPECT_EQ(status, napi_ok);
827 status = napi_release_threadsafe_function(tsFunc, napi_tsfn_abort);
828 EXPECT_EQ(status, napi_ok);
829 if (uv_thread_create(&g_uvThreadTest5, TsFuncDataSourceThreadAbort, tsFunc) != 0) {
830 HILOG_ERROR("Failed to create uv thread!");
831 }
832
833 HILOG_INFO("Threadsafe_Test_0400 end");
834 }
835
836 /**
837 * @tc.name: ThreadsafeTest005
838 * @tc.desc: Test initial_thread_count not enough.
839 * @tc.type: FUNC
840 * @tc.require: I5K6KF
841 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest005, testing::ext::TestSize.Level1)842 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest005, testing::ext::TestSize.Level1)
843 {
844 HILOG_INFO("Threadsafe_Test_0500 start");
845 napi_env env = (napi_env)engine_;
846 napi_threadsafe_function tsFunc = nullptr;
847 napi_value resourceName = 0;
848 g_callSuccessCountJS = 0;
849 g_callSuccessCount = 0;
850 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
851 g_mainTid = gettid();
852 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
853 g_finalData.id = FINAL_CB_DATA_TEST_ID;
854
855 auto status = napi_create_threadsafe_function(env,
856 nullptr,
857 nullptr,
858 resourceName,
859 0,
860 2,
861 &g_finalData,
862 TsFuncFinalTotal,
863 &g_jsData,
864 TsFuncCallJsTwo,
865 &tsFunc);
866 EXPECT_EQ(status, napi_ok);
867 int threadCount = THREAD_COUNT_FOUR;
868 acquireFlag = false;
869
870 for (int i = 0; i < threadCount; i++) {
871 if (uv_thread_create(&g_uvThreadTest6, TsFuncDataSourceThreadCountTotal, tsFunc) != 0) {
872 HILOG_ERROR("Failed to create uv thread!");
873 }
874 }
875
876 usleep(200 * 1000);
877 EXPECT_EQ(g_callSuccessCount, SUCCESS_COUNT_JS_FOUR);
878 HILOG_INFO("Threadsafe_Test_0500 end");
879 }
880
881 /**
882 * @tc.name: ThreadsafeTest006
883 * @tc.desc: Test initial_thread_count not enough but acquire.
884 * @tc.type: FUNC
885 * @tc.require: I5K6KF
886 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest006, testing::ext::TestSize.Level1)887 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest006, testing::ext::TestSize.Level1)
888 {
889 HILOG_INFO("Threadsafe_Test_0600 start");
890 napi_env env = (napi_env)engine_;
891 napi_threadsafe_function tsFunc = nullptr;
892 napi_value resourceName = 0;
893 g_callSuccessCount = 0;
894 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
895 g_mainTid = gettid();
896 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
897 g_finalData.id = FINAL_CB_DATA_TEST_ID;
898
899 auto status = napi_create_threadsafe_function(env,
900 nullptr,
901 nullptr,
902 resourceName,
903 0,
904 1,
905 &g_finalData,
906 TsFuncFinalTotalFour,
907 &g_jsData,
908 TsFuncCallJsFour,
909 &tsFunc);
910 EXPECT_EQ(status, napi_ok);
911 int threadCount = THREAD_COUNT_FOUR;
912 acquireFlag = true;
913
914 for (int i = 0; i < threadCount; i++) {
915 if (uv_thread_create(&g_uvThreadTest7, TsFuncDataSourceThreadCountTotal, tsFunc) != 0) {
916 HILOG_ERROR("Failed to create uv thread!");
917 }
918 }
919
920 usleep(200 * 1000);
921 EXPECT_EQ(g_callSuccessCount, SUCCESS_COUNT_JS_FOUR);
922 HILOG_INFO("Threadsafe_Test_0600 end");
923 }
924
925 /**
926 * @tc.name: ThreadsafeTest007
927 * @tc.desc: Test napi_ref_threadsafe_function.
928 * @tc.type: FUNC
929 * @tc.require: I5K6KF
930 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest007, testing::ext::TestSize.Level1)931 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest007, testing::ext::TestSize.Level1)
932 {
933 HILOG_INFO("Threadsafe_Test_0700 start");
934
935 napi_env env = (napi_env)engine_;
936 napi_threadsafe_function tsFunc = nullptr;
937 napi_value resourceName = 0;
938
939 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
940 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
941 g_finalData.id = FINAL_CB_DATA_TEST_ID;
942
943 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
944 0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
945 EXPECT_EQ(status, napi_ok);
946
947 status = napi_ref_threadsafe_function(env, tsFunc);
948 EXPECT_EQ(status, napi_ok);
949
950 HILOG_INFO("Threadsafe_Test_0700 end");
951 }
952
953 /**
954 * @tc.name: ThreadsafeTest008
955 * @tc.desc: Test napi_unref_threadsafe_function.
956 * @tc.type: FUNC
957 * @tc.require: I5K6KF
958 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest008, testing::ext::TestSize.Level1)959 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest008, testing::ext::TestSize.Level1)
960 {
961 HILOG_INFO("Threadsafe_Test_0800 start");
962 napi_env env = (napi_env)engine_;
963 napi_threadsafe_function tsFunc = nullptr;
964 napi_value resourceName = 0;
965
966 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
967 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
968 g_finalData.id = FINAL_CB_DATA_TEST_ID;
969
970 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
971 0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
972 EXPECT_EQ(status, napi_ok);
973
974 status = napi_unref_threadsafe_function(env, tsFunc);
975 EXPECT_EQ(status, napi_ok);
976
977 HILOG_INFO("Threadsafe_Test_0800 end");
978 }
979
980 /**
981 * @tc.name: ThreadsafeTest009
982 * @tc.desc: Test napi_ref_threadsafe_function and napi_unref_threadsafe_function.
983 * @tc.type: FUNC
984 * @tc.require: I5K6KF
985 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest009, testing::ext::TestSize.Level1)986 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest009, testing::ext::TestSize.Level1)
987 {
988 HILOG_INFO("Threadsafe_Test_0900 start");
989 napi_env env = (napi_env)engine_;
990 napi_threadsafe_function tsFunc = nullptr;
991 napi_value resourceName = 0;
992
993 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
994 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
995 g_finalData.id = FINAL_CB_DATA_TEST_ID;
996
997 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
998 0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
999 EXPECT_EQ(status, napi_ok);
1000
1001 status = napi_unref_threadsafe_function(env, tsFunc);
1002 EXPECT_EQ(status, napi_ok);
1003
1004 status = napi_unref_threadsafe_function(env, tsFunc);
1005 EXPECT_EQ(status, napi_ok);
1006
1007 HILOG_INFO("Threadsafe_Test_0900 end");
1008 }
1009
1010 /**
1011 * @tc.name: ThreadsafeTest010
1012 * @tc.desc: Test napi_unref_threadsafe_function and napi_release_threadsafe_function.
1013 * @tc.type: FUNC
1014 * @tc.require: I5K6KF
1015 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest010, testing::ext::TestSize.Level1)1016 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest010, testing::ext::TestSize.Level1)
1017 {
1018 HILOG_INFO("Threadsafe_Test_1000 start");
1019 napi_env env = (napi_env)engine_;
1020 napi_threadsafe_function tsFunc = nullptr;
1021 napi_value resourceName = 0;
1022 napi_threadsafe_function_release_mode abort = napi_tsfn_abort;
1023
1024 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1025 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1026 g_finalData.id = FINAL_CB_DATA_TEST_ID;
1027
1028 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1029 0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1030 EXPECT_EQ(status, napi_ok);
1031
1032 status = napi_unref_threadsafe_function(env, tsFunc);
1033 EXPECT_EQ(status, napi_ok);
1034
1035 status = napi_release_threadsafe_function(tsFunc, abort);
1036 EXPECT_EQ(status, napi_ok);
1037
1038 HILOG_INFO("Threadsafe_Test_1000 end");
1039 }
1040
1041 /**
1042 * @tc.name: ThreadsafeTest011
1043 * @tc.desc: Test napi_ref_threadsafe_function and napi_release_threadsafe_function.
1044 * @tc.type: FUNC
1045 * @tc.require: I5K6KF
1046 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest011, testing::ext::TestSize.Level1)1047 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest011, testing::ext::TestSize.Level1)
1048 {
1049 HILOG_INFO("Threadsafe_Test_1100 start");
1050
1051 napi_env env = (napi_env)engine_;
1052 napi_threadsafe_function tsFunc = nullptr;
1053 napi_value resourceName = 0;
1054 napi_threadsafe_function_release_mode abort = napi_tsfn_abort;
1055
1056 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1057 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1058 g_finalData.id = FINAL_CB_DATA_TEST_ID;
1059
1060 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1061 0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1062 EXPECT_EQ(status, napi_ok);
1063
1064 status = napi_ref_threadsafe_function(env, tsFunc);
1065 EXPECT_EQ(status, napi_ok);
1066
1067 status = napi_release_threadsafe_function(tsFunc, abort);
1068 EXPECT_EQ(status, napi_ok);
1069
1070 HILOG_INFO("Threadsafe_Test_1100 end");
1071 }
1072
1073 /**
1074 * @tc.name: ThreadsafeWithPriorityArgsCheckTest001
1075 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1076 * @tc.type: FUNC
1077 * @tc.require: I99QUH
1078 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest001, testing::ext::TestSize.Level1)1079 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest001, testing::ext::TestSize.Level1)
1080 {
1081 HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest001 start");
1082 auto status =
1083 napi_call_threadsafe_function_with_priority(nullptr, nullptr, napi_priority_immediate, true);
1084 EXPECT_EQ(status, napi_invalid_arg);
1085 HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest001 end");
1086 }
1087
1088 /**
1089 * @tc.name: ThreadsafeWithPriorityArgsCheckTest002
1090 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1091 * @tc.type: FUNC
1092 * @tc.require: I99QUH
1093 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest002, testing::ext::TestSize.Level1)1094 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest002, testing::ext::TestSize.Level1)
1095 {
1096 HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest002 start");
1097 napi_env env = (napi_env)engine_;
1098 napi_value resourceName = 0;
1099 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1100 CallbackData *callbackData = new CallbackData();
1101 auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1102 0, 1, callbackData, nullptr, callbackData, CallJs, &callbackData->tsfn);
1103 EXPECT_EQ(status, napi_ok);
1104 status =
1105 napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr,
1106 static_cast<napi_task_priority>(INVALID_NAPI_THREAD_SAFE_PRIORITY), true);
1107 delete callbackData;
1108 HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest002 end");
1109 }
1110
1111 /**
1112 * @tc.name: ThreadsafeWithPriorityTest001
1113 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1114 * @tc.type: FUNC
1115 * @tc.require: I99QUH
1116 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest001, testing::ext::TestSize.Level1)1117 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest001, testing::ext::TestSize.Level1)
1118 {
1119 HILOG_INFO("ThreadsafeWithPriorityTest001 start");
1120 g_isTailA = true;
1121 g_isTailB = true;
1122 auto task = [test = this]() {
1123 test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
1124 };
1125 EXPECT_NE(eventHandler_, nullptr);
1126 eventHandler_->PostTask(task);
1127 auto runner = eventHandler_->GetEventRunner();
1128 EXPECT_NE(runner, nullptr);
1129 runner->Run();
1130 HILOG_INFO("ThreadsafeWithPriorityTest001 end");
1131 }
1132
1133 /**
1134 * @tc.name: ThreadsafeWithPriorityTest002
1135 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1136 * @tc.type: FUNC
1137 * @tc.require: I99QUH
1138 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest002, testing::ext::TestSize.Level1)1139 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest002, testing::ext::TestSize.Level1)
1140 {
1141 HILOG_INFO("ThreadsafeWithPriorityTest002 start");
1142 g_isTailA = false;
1143 g_isTailB = false;
1144 auto task = [test = this]() {
1145 test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
1146 };
1147 EXPECT_NE(eventHandler_, nullptr);
1148 eventHandler_->PostTask(task);
1149 auto runner = eventHandler_->GetEventRunner();
1150 EXPECT_NE(runner, nullptr);
1151 runner->Run();
1152 HILOG_INFO("ThreadsafeWithPriorityTest002 end");
1153 }
1154
1155 /**
1156 * @tc.name: ThreadsafeWithPriorityTest003
1157 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1158 * @tc.type: FUNC
1159 * @tc.require: I99QUH
1160 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest003, testing::ext::TestSize.Level1)1161 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest003, testing::ext::TestSize.Level1)
1162 {
1163 HILOG_INFO("ThreadsafeWithPriorityTest003 start");
1164 g_isTailA = true;
1165 g_isTailB = false;
1166 auto task = [test = this]() {
1167 test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
1168 };
1169 EXPECT_NE(eventHandler_, nullptr);
1170 eventHandler_->PostTask(task);
1171 auto runner = eventHandler_->GetEventRunner();
1172 EXPECT_NE(runner, nullptr);
1173 runner->Run();
1174 HILOG_INFO("ThreadsafeWithPriorityTest003 end");
1175 }
1176
1177 /**
1178 * @tc.name: ThreadsafeWithPriorityTest004
1179 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1180 * @tc.type: FUNC
1181 * @tc.require: I99QUH
1182 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest004, testing::ext::TestSize.Level1)1183 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest004, testing::ext::TestSize.Level1)
1184 {
1185 HILOG_INFO("ThreadsafeWithPriorityTest004 start");
1186 g_isTailA = true;
1187 g_isTailB = true;
1188 auto task = [test = this]() {
1189 test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1190 };
1191 EXPECT_NE(eventHandler_, nullptr);
1192 eventHandler_->PostTask(task);
1193 auto runner = eventHandler_->GetEventRunner();
1194 EXPECT_NE(runner, nullptr);
1195 runner->Run();
1196 HILOG_INFO("ThreadsafeWithPriorityTest004 end");
1197 }
1198
1199 /**
1200 * @tc.name: ThreadsafeWithPriorityTest005
1201 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1202 * @tc.type: FUNC
1203 * @tc.require: I99QUH
1204 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest005, testing::ext::TestSize.Level1)1205 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest005, testing::ext::TestSize.Level1)
1206 {
1207 HILOG_INFO("ThreadsafeWithPriorityTest005 start");
1208 g_isTailA = false;
1209 g_isTailB = false;
1210 auto task = [test = this]() {
1211 test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1212 };
1213 EXPECT_NE(eventHandler_, nullptr);
1214 eventHandler_->PostTask(task);
1215 auto runner = eventHandler_->GetEventRunner();
1216 EXPECT_NE(runner, nullptr);
1217 runner->Run();
1218 HILOG_INFO("ThreadsafeWithPriorityTest005 end");
1219 }
1220
1221 /**
1222 * @tc.name: ThreadsafeWithPriorityTest006
1223 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1224 * @tc.type: FUNC
1225 * @tc.require: I99QUH
1226 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest006, testing::ext::TestSize.Level1)1227 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest006, testing::ext::TestSize.Level1)
1228 {
1229 HILOG_INFO("ThreadsafeWithPriorityTest006 start");
1230 g_isTailA = true;
1231 g_isTailB = false;
1232 auto task = [test = this]() {
1233 test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1234 };
1235 EXPECT_NE(eventHandler_, nullptr);
1236 eventHandler_->PostTask(task);
1237 auto runner = eventHandler_->GetEventRunner();
1238 EXPECT_NE(runner, nullptr);
1239 runner->Run();
1240 HILOG_INFO("ThreadsafeWithPriorityTest006 end");
1241 }
1242
1243 /**
1244 * @tc.name: ThreadsafeWithPriorityTest007
1245 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1246 * @tc.type: FUNC
1247 * @tc.require: I99QUH
1248 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest007, testing::ext::TestSize.Level1)1249 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest007, testing::ext::TestSize.Level1)
1250 {
1251 HILOG_INFO("ThreadsafeWithPriorityTest007 start");
1252 g_isTailA = true;
1253 g_isTailB = true;
1254 auto task = [test = this]() {
1255 test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1256 };
1257 EXPECT_NE(eventHandler_, nullptr);
1258 eventHandler_->PostTask(task);
1259 auto runner = eventHandler_->GetEventRunner();
1260 EXPECT_NE(runner, nullptr);
1261 runner->Run();
1262 HILOG_INFO("ThreadsafeWithPriorityTest007 end");
1263 }
1264
1265 /**
1266 * @tc.name: ThreadsafeWithPriorityTest008
1267 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1268 * @tc.type: FUNC
1269 * @tc.require: I99QUH
1270 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest008, testing::ext::TestSize.Level1)1271 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest008, testing::ext::TestSize.Level1)
1272 {
1273 HILOG_INFO("ThreadsafeWithPriorityTest008 start");
1274 g_isTailA = false;
1275 g_isTailB = false;
1276 auto task = [test = this]() {
1277 test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1278 };
1279 EXPECT_NE(eventHandler_, nullptr);
1280 eventHandler_->PostTask(task);
1281 auto runner = eventHandler_->GetEventRunner();
1282 EXPECT_NE(runner, nullptr);
1283 runner->Run();
1284 HILOG_INFO("ThreadsafeWithPriorityTest008 end");
1285 }
1286
1287 /**
1288 * @tc.name: ThreadsafeWithPriorityTest009
1289 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1290 * @tc.type: FUNC
1291 * @tc.require: I99QUH
1292 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest009, testing::ext::TestSize.Level1)1293 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest009, testing::ext::TestSize.Level1)
1294 {
1295 HILOG_INFO("ThreadsafeWithPriorityTest009 start");
1296 g_isTailA = true;
1297 g_isTailB = false;
1298 auto task = [test = this]() {
1299 test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1300 };
1301 EXPECT_NE(eventHandler_, nullptr);
1302 eventHandler_->PostTask(task);
1303 auto runner = eventHandler_->GetEventRunner();
1304 EXPECT_NE(runner, nullptr);
1305 runner->Run();
1306 HILOG_INFO("ThreadsafeWithPriorityTest009 end");
1307 }
1308
1309
1310 /**
1311 * @tc.name: ThreadsafeWithPriorityTest010
1312 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1313 * @tc.type: FUNC
1314 * @tc.require: I99QUH
1315 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest010, testing::ext::TestSize.Level1)1316 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest010, testing::ext::TestSize.Level1)
1317 {
1318 HILOG_INFO("ThreadsafeWithPriorityTest010 start");
1319 g_isTailA = true;
1320 g_isTailB = true;
1321 auto task = [test = this]() {
1322 test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1323 };
1324 EXPECT_NE(eventHandler_, nullptr);
1325 eventHandler_->PostTask(task);
1326 auto runner = eventHandler_->GetEventRunner();
1327 EXPECT_NE(runner, nullptr);
1328 runner->Run();
1329 HILOG_INFO("ThreadsafeWithPriorityTest010 end");
1330 }
1331
1332 /**
1333 * @tc.name: ThreadsafeWithPriorityTest011
1334 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1335 * @tc.type: FUNC
1336 * @tc.require: I99QUH
1337 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest011, testing::ext::TestSize.Level1)1338 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest011, testing::ext::TestSize.Level1)
1339 {
1340 HILOG_INFO("ThreadsafeWithPriorityTest005 start");
1341 g_isTailA = false;
1342 g_isTailB = false;
1343 auto task = [test = this]() {
1344 test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1345 };
1346 EXPECT_NE(eventHandler_, nullptr);
1347 eventHandler_->PostTask(task);
1348 auto runner = eventHandler_->GetEventRunner();
1349 EXPECT_NE(runner, nullptr);
1350 runner->Run();
1351 HILOG_INFO("ThreadsafeWithPriorityTest011 end");
1352 }
1353
1354 /**
1355 * @tc.name: ThreadsafeWithPriorityTest012
1356 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1357 * @tc.type: FUNC
1358 * @tc.require: I99QUH
1359 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest012, testing::ext::TestSize.Level1)1360 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest012, testing::ext::TestSize.Level1)
1361 {
1362 HILOG_INFO("ThreadsafeWithPriorityTest012 start");
1363 g_isTailA = true;
1364 g_isTailB = false;
1365 auto task = [test = this]() {
1366 test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1367 };
1368 EXPECT_NE(eventHandler_, nullptr);
1369 eventHandler_->PostTask(task);
1370 auto runner = eventHandler_->GetEventRunner();
1371 EXPECT_NE(runner, nullptr);
1372 runner->Run();
1373 HILOG_INFO("ThreadsafeWithPriorityTest012 end");
1374 }
1375
1376 /**
1377 * @tc.name: ThreadsafeWithPriorityTest013
1378 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1379 * @tc.type: FUNC
1380 * @tc.require: I99QUH
1381 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest013, testing::ext::TestSize.Level1)1382 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest013, testing::ext::TestSize.Level1)
1383 {
1384 HILOG_INFO("ThreadsafeWithPriorityTest013 start");
1385 auto task = [test = this]() {
1386 test->CallThreadSafeWithDiffPriorityTest();
1387 };
1388 EXPECT_NE(eventHandler_, nullptr);
1389 eventHandler_->PostTask(task);
1390 auto runner = eventHandler_->GetEventRunner();
1391 EXPECT_NE(runner, nullptr);
1392 runner->Run();
1393 HILOG_INFO("ThreadsafeWithPriorityTest013 end");
1394 }
1395
1396 /**
1397 * @tc.name: ThreadsafeWithPriorityTest014
1398 * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1399 * @tc.type: FUNC
1400 * @tc.require: I99QUH
1401 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest014, testing::ext::TestSize.Level1)1402 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest014, testing::ext::TestSize.Level1)
1403 {
1404 HILOG_INFO("ThreadsafeWithPriorityTest014 start");
1405 auto task = [test = this]() {
1406 test->CallThreadSafeWithDiffPriorityMultipleThreadTest();
1407 };
1408 EXPECT_NE(eventHandler_, nullptr);
1409 eventHandler_->PostTask(task);
1410 auto runner = eventHandler_->GetEventRunner();
1411 EXPECT_NE(runner, nullptr);
1412 runner->Run();
1413 HILOG_INFO("ThreadsafeWithPriorityTest014 end");
1414 }
1415
1416 /**
1417 * @tc.name: ThreadsafeTest012
1418 * @tc.desc: Test LoadModule Func, call napi_call_threadsafe_function in callback.
1419 * @tc.type: FUNC
1420 * @tc.require: I5K6KF
1421 */
HWTEST_F(NapiThreadsafeTest, ThreadsafeTest012, testing::ext::TestSize.Level1)1422 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest012, testing::ext::TestSize.Level1)
1423 {
1424 HILOG_INFO("Threadsafe_Test_1200 start");
1425 napi_env env = (napi_env)engine_;
1426 napi_threadsafe_function tsFunc = nullptr;
1427 napi_value resourceName = 0;
1428
1429 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1430 g_mainTid = gettid();
1431 g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1432 g_finalData.id = FINAL_CB_DATA_TEST_ID;
1433
1434 auto status = napi_create_threadsafe_function(env,
1435 nullptr,
1436 nullptr,
1437 resourceName,
1438 0,
1439 1,
1440 &g_finalData,
1441 TsFuncFinal,
1442 &g_jsData,
1443 TsFuncCallJsWithNewCall,
1444 &tsFunc);
1445 EXPECT_EQ(status, napi_ok);
1446
1447 if (uv_thread_create(
1448 &g_uvThread,
1449 [](void *data) {
1450 napi_threadsafe_function func = (napi_threadsafe_function)data;
1451 auto status = napi_call_threadsafe_function(func, data, napi_tsfn_nonblocking);
1452 EXPECT_EQ(status, napi_ok);
1453 },
1454 tsFunc) != 0) {
1455 HILOG_ERROR("Failed to create uv thread!");
1456 }
1457
1458 HILOG_INFO("Threadsafe_Test_1200 end");
1459 }