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