• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define protected public
17 
18 #include "test.h"
19 
20 #include <chrono>
21 #include <thread>
22 #include <uv.h>
23 
24 #include "event_runner.h"
25 #include "napi/native_api.h"
26 #include "napi/native_node_api.h"
27 #include "native_safe_async_work.h"
28 #include "securec.h"
29 #include "utils/log.h"
30 
31 struct CallJsCbData_t {
32     int32_t id = 0;
33     bool secondaryThread = false;
34     napi_threadsafe_function_call_mode blockOnFull = napi_tsfn_nonblocking;
35 };
36 
37 struct FinalCbData_t {
38     int32_t id = 0;
39 };
40 
41 struct CallbackData {
42     napi_threadsafe_function tsfn;
43     napi_async_work work;
44     napi_task_priority priority;
45     int32_t taskSize;
46     int32_t version;
47 };
48 
49 static constexpr int32_t SEND_DATA_TEST = 11;
50 static constexpr int32_t CALL_JS_CB_DATA_TEST_ID = 101;
51 static constexpr int32_t FINAL_CB_DATA_TEST_ID = 1001;
52 static constexpr int32_t SEND_DATAS_LENGTH = 10;
53 static constexpr int32_t THREAD_COUNT = 2;
54 static constexpr int32_t THREAD_COUNT_FOUR = 4;
55 static constexpr int32_t MAX_QUEUE_SIZE = 3;
56 static constexpr int32_t SUCCESS_COUNT_JS_FOUR = 4;
57 static constexpr int32_t INVALID_NAPI_THREAD_SAFE_PRIORITY = -1;
58 static constexpr int32_t FIRST_RECEIVER = 1;
59 static constexpr int32_t SECOND_RECEIVER = 2;
60 static constexpr int32_t THIRD_RECEIVER = 3;
61 static constexpr int32_t FOURTH_RECEIVER = 4;
62 static constexpr int32_t FIFTH_RECEIVER = 5;
63 static constexpr int32_t DATA_LENGTH = 40;
64 static constexpr int32_t THREAD_SIZE = 5;
65 static constexpr int32_t SECOND_THREAD_INDEX = 1;
66 static constexpr int32_t THIRD_THREAD_INDEX = 2;
67 static constexpr int32_t FOURTH_THREAD_INDEX = 3;
68 static constexpr int32_t FIFTH_THREAD_INDEX = 4;
69 static constexpr int32_t API_VERSION_FIFTEEN = 15;
70 static constexpr int32_t API_VERSION_SIXTEEN = 16;
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     }
319     status = napi_call_threadsafe_function(func, &g_sendData, blockMode);
320     if (status == napi_ok) {
321         g_callSuccessCount++;
322     }
323     status = napi_release_threadsafe_function(func, napi_tsfn_release);
324 }
325 
TsFuncDataSourceThreadMulti(void * data)326 static void TsFuncDataSourceThreadMulti(void* data)
327 {
328     HILOG_INFO("TsFuncDataSourceThreadMulti called");
329 
330     // expect thread id not equal
331     EXPECT_NE(gettid(), g_mainTid);
332 
333     napi_threadsafe_function func =  (napi_threadsafe_function)data;
334     void* context = nullptr;
335 
336     auto status = napi_get_threadsafe_function_context(func, &context);
337     EXPECT_EQ(status, napi_ok);
338     CallJsCbData_t* jsData = nullptr;
339     jsData = (CallJsCbData_t*)context;
340 
341     if (jsData->secondaryThread) {
342         status = napi_acquire_threadsafe_function(func);
343         EXPECT_EQ(status, napi_ok);
344 
345         if (uv_thread_create(&g_uvThreadSecondary, TsFuncSecondaryThread, func) != 0) {
346             HILOG_ERROR("Failed to create uv thread!");
347         }
348     }
349 
350     bool queueClosing = false;
351     bool queueFull = false;
352     int32_t index = 0;
353     for (index = SEND_DATAS_LENGTH - 1; index > -1 && !queueClosing; index--) {
354         g_sendDatas[index] = index;
355         status = napi_call_threadsafe_function(func, &g_sendDatas[index], jsData->blockOnFull);
356         HILOG_INFO("napi_call_threadsafe_function index %d status %d", index, status);
357 
358         switch (status) {
359             case napi_queue_full:
360                 queueFull = true;
361                 index++;
362                 [[fallthrough]];
363             case napi_ok:
364                 continue;
365             case napi_closing:
366                 queueClosing = true;
367                 break;
368             default:
369                 HILOG_ERROR("Failed to call napi_call_threadsafe_function!");
370         }
371     }
372 
373     if (!queueClosing && (napi_release_threadsafe_function(func, napi_tsfn_release) != napi_ok)) {
374         HILOG_ERROR("Failed to call napi_release_threadsafe_function!");
375     }
376 }
377 
TsFuncThreadInternal(napi_env env,napi_threadsafe_function_call_js cb,uv_thread_t & uvThread,bool secondary,bool block)378 static void TsFuncThreadInternal(napi_env env,
379                                  napi_threadsafe_function_call_js cb,
380                                  uv_thread_t& uvThread,
381                                  bool secondary,
382                                  bool block)
383 {
384     HILOG_INFO("TsFuncThreadInternal start secondary %d block %d", secondary, block);
385 
386     napi_threadsafe_function tsFunc = nullptr;
387     napi_value resourceName = 0;
388 
389     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
390     g_mainTid = gettid();
391 
392     g_jsDataInternal.id = CALL_JS_CB_DATA_TEST_ID;
393     g_jsDataInternal.secondaryThread = (secondary ? true : false);
394     g_jsDataInternal.blockOnFull = (block ? napi_tsfn_blocking : napi_tsfn_nonblocking);
395 
396     auto status = napi_create_threadsafe_function(env,
397                                                   nullptr,
398                                                   nullptr,
399                                                   resourceName,
400                                                   MAX_QUEUE_SIZE,
401                                                   THREAD_COUNT,
402                                                   &uvThread,
403                                                   TsFuncFinalJoinThread,
404                                                   &g_jsDataInternal,
405                                                   cb,
406                                                   &tsFunc);
407     EXPECT_EQ(status, napi_ok);
408 
409     if (uv_thread_create(&uvThread, TsFuncDataSourceThreadMulti, tsFunc) != 0) {
410         HILOG_ERROR("Failed to create uv thread!");
411     }
412 
413     HILOG_INFO("TsFuncThreadInternal end");
414 }
415 
StopCurrentRunner()416 static void StopCurrentRunner()
417 {
418     auto runner = OHOS::AppExecFwk::EventRunner::Current();
419     if (runner != nullptr) {
420         HILOG_INFO("Stop the current runner!");
421         runner->Stop();
422     }
423 }
424 
ThreadFanalize(napi_env env,void * context,void *)425 void ThreadFanalize(napi_env env, void* context, void*)
426 {
427     StopCurrentRunner();
428     delete reinterpret_cast<CallbackData *>(context);
429 }
430 
CallJs(napi_env env,napi_value jsCb,void * context,void * data)431 static void CallJs(napi_env env, napi_value jsCb, void *context, void *data)
432 {
433     napi_release_threadsafe_function(reinterpret_cast<CallbackData*>(context)->tsfn, napi_tsfn_release);
434 
435     g_receiveCnt++;
436     if (g_receiveCnt == FIRST_RECEIVER) {
437         return;
438     }
439     // check data string
440     char *testData = reinterpret_cast<char *>(data);
441     EXPECT_NE(testData, nullptr) << "testData is nullptr";
442     int32_t ret = 0;
443     if (g_receiveCnt == SECOND_RECEIVER) {
444         if (!g_isTailB) {
445             ret = strcmp(testData, "hello world from B");
446         } else {
447             ret = strcmp(testData, "hello world from A");
448         }
449     }
450     if (g_receiveCnt == THIRD_RECEIVER) {
451         if (!g_isTailB) {
452             ret = strcmp(testData, "hello world from A");
453         } else {
454             ret = strcmp(testData, "hello world from B");
455         }
456     }
457     EXPECT_EQ(ret, 0);
458 }
459 
CallJsWithDiffPriority(napi_env env,napi_value jsCb,void * context,void * data)460 static void CallJsWithDiffPriority(napi_env env, napi_value jsCb, void *context, void *data)
461 {
462     EXPECT_NE(env, nullptr);
463     auto ctx = reinterpret_cast<CallbackData *>(context);
464     g_receiveCnt++;
465     napi_release_threadsafe_function(ctx->tsfn, napi_tsfn_release);
466     ctx->taskSize--;
467     if (g_receiveCnt == FIRST_RECEIVER) {
468         return;
469     }
470     // check data string
471     char *testData = reinterpret_cast<char *>(data);
472     EXPECT_NE(testData, nullptr) << "testData is nullptr";
473     int32_t ret = 0;
474     if (g_receiveCnt == SECOND_RECEIVER) {
475         ret = strcmp(testData, "hello world from A");
476     } else if (g_receiveCnt == THIRD_RECEIVER) {
477         ret = strcmp(testData, "hello world from B");
478     } else if (g_receiveCnt == FOURTH_RECEIVER) {
479         ret = strcmp(testData, "hello world from C");
480     } else if (g_receiveCnt == FIFTH_RECEIVER) {
481         ret = strcmp(testData, "hello world from D");
482     }
483     EXPECT_EQ(ret, 0) << "data is: " << testData << ", execute id: " << g_receiveCnt;
484 }
485 
486 class UnitLoopHandler : public OHOS::AppExecFwk::FileDescriptorListener,
487     public std::enable_shared_from_this<UnitLoopHandler> {
488 public:
UnitLoopHandler(uv_loop_t * uvLoop)489     explicit UnitLoopHandler(uv_loop_t* uvLoop) : uvLoop_(uvLoop) {}
OnReadable(int32_t)490     void OnReadable(int32_t) override { uv_run(uvLoop_, UV_RUN_NOWAIT); }
OnWritable(int32_t)491     void OnWritable(int32_t) override { uv_run(uvLoop_, UV_RUN_NOWAIT); }
492 
493 private:
494     uv_loop_t* uvLoop_ = nullptr;
495 };
496 
497 class NapiThreadsafeTest : public NativeEngineTest {
498 public:
SetUpTestCase()499     static void SetUpTestCase()
500     {
501         GTEST_LOG_(INFO) << "NapiThreadsafeTest SetUpTestCase";
502     }
503 
TearDownTestCase()504     static void TearDownTestCase()
505     {
506         GTEST_LOG_(INFO) << "NapiThreadsafeTest TearDownTestCase";
507     }
508 
SetUp()509     void SetUp() override { AttachEventHandler(); }
TearDown()510     void TearDown() override {}
511 
512     void CallThreadSafeWithSamePriorityTest(napi_task_priority priority);
513     void CallThreadSafeWithDiffPriorityTest();
514     void CallThreadSafeWithDiffPriorityTest01();
515     void CallThreadSafeWithDiffPriorityTest02();
516     void CallThreadSafeWithDiffPriorityMultipleThreadTest();
517     void AttachEventHandler();
518 };
519 
AttachEventHandler()520 void NapiThreadsafeTest::AttachEventHandler()
521 {
522     if (eventHandler_ != nullptr) {
523         return;
524     }
525     auto uvLoop = engine_->GetUVLoop();
526     auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
527     EXPECT_GE(fd, 0);
528     uv_run(uvLoop, UV_RUN_NOWAIT);
529     auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
530     EXPECT_NE(runner, nullptr);
531     eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
532     EXPECT_NE(eventHandler_, nullptr);
533     uint32_t events = OHOS::AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT | OHOS::AppExecFwk::FILE_DESCRIPTOR_OUTPUT_EVENT;
534     eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared<UnitLoopHandler>(uvLoop), "uvLoopTask");
535     HILOG_INFO("AttachEventHandler is completed!");
536 }
537 
538 class AutoTsfn {
539 public:
AutoTsfn(napi_threadsafe_function tsfn)540     explicit AutoTsfn(napi_threadsafe_function tsfn) : tsfn_(tsfn) {}
~AutoTsfn()541     ~AutoTsfn()
542     {
543         if (autoRelease_) {
544             Release();
545         }
546     }
547 
Acquire()548     void Acquire()
549     {
550         ASSERT_EQ(napi_acquire_threadsafe_function(tsfn_), napi_ok);
551     }
552 
Release()553     void Release()
554     {
555         ASSERT_EQ(napi_release_threadsafe_function(tsfn_, napi_tsfn_release), napi_ok);
556     }
557 
CancelRelease()558     void CancelRelease()
559     {
560         autoRelease_ = false;
561     }
562 
563 private:
564     napi_threadsafe_function tsfn_ {nullptr};
565     bool autoRelease_ {true};
566 };
567 
CallThreadSafeFunc(napi_threadsafe_function tsfn,AutoTsfn & autoTsfn,napi_task_priority priority)568 static void CallThreadSafeFunc(napi_threadsafe_function tsfn, AutoTsfn& autoTsfn, napi_task_priority priority)
569 {
570     char *testData = (char *)malloc(DATA_LENGTH);
571     if (testData == nullptr) {
572         return;
573     }
574     memset_s(testData, DATA_LENGTH, 0, DATA_LENGTH);
575     if (priority == napi_priority_immediate) {
576         strcpy_s(testData, DATA_LENGTH, "hello world from A");
577     } else if (priority == napi_priority_high) {
578         strcpy_s(testData, DATA_LENGTH, "hello world from B");
579     } else if (priority == napi_priority_low) {
580         strcpy_s(testData, DATA_LENGTH, "hello world from C");
581     } else if (priority == napi_priority_idle) {
582         strcpy_s(testData, DATA_LENGTH, "hello world from D");
583     }
584     autoTsfn.Acquire();
585     auto status = napi_call_threadsafe_function_with_priority(tsfn, testData, priority, true);
586     if (status != napi_ok) {
587         autoTsfn.Release();
588     }
589     EXPECT_EQ(status, napi_ok);
590 }
591 
CallThreadSafeFunc(napi_threadsafe_function tsfn,AutoTsfn & autoTsfn,char * testData,napi_task_priority priority,bool isTail)592 static void CallThreadSafeFunc(
593     napi_threadsafe_function tsfn, AutoTsfn &autoTsfn, char *testData, napi_task_priority priority, bool isTail)
594 {
595     autoTsfn.Acquire();
596     auto status = napi_call_threadsafe_function_with_priority(tsfn, testData, priority, isTail);
597     if (status != napi_ok) {
598         autoTsfn.Release();
599     }
600     EXPECT_EQ(status, napi_ok);
601 }
602 
CallThreadSafeWithSamePriorityTest(napi_task_priority priority)603 void NapiThreadsafeTest::CallThreadSafeWithSamePriorityTest(napi_task_priority priority)
604 {
605     napi_env env = (napi_env)engine_;
606     napi_value resourceName = 0;
607     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
608     CallbackData *callbackData = new CallbackData();
609     callbackData->priority = priority;
610 
611     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
612         0, 1, callbackData, ThreadFanalize, callbackData, CallJs, &callbackData->tsfn);
613     EXPECT_EQ(status, napi_ok);
614     std::thread([](napi_env env, void* data) {
615         CallbackData* callbackData = (CallbackData*)data;
616         g_receiveCnt = 1;
617 
618         char *testDataA = (char *)malloc(DATA_LENGTH);
619         memset_s(testDataA, DATA_LENGTH, 0, DATA_LENGTH);
620         strcpy_s(testDataA, DATA_LENGTH, "hello world from A");
621 
622         char *testDataB = (char *)malloc(DATA_LENGTH);
623         memset_s(testDataB, DATA_LENGTH, 0, DATA_LENGTH);
624         strcpy_s(testDataB, DATA_LENGTH, "hello world from B");
625 
626         AutoTsfn tsfn(callbackData->tsfn);
627         CallThreadSafeFunc(callbackData->tsfn, tsfn, testDataA, callbackData->priority, g_isTailA);
628         CallThreadSafeFunc(callbackData->tsfn, tsfn, testDataB, callbackData->priority, g_isTailB);
629     }, env, callbackData).join();
630 }
631 
CallThreadSafeWithDiffPriorityTest()632 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityTest()
633 {
634     napi_env env = (napi_env)engine_;
635     napi_value resourceName = 0;
636     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
637     CallbackData *callbackData = new CallbackData();
638 
639     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
640         0, 1, callbackData, ThreadFanalize, callbackData, CallJsWithDiffPriority, &callbackData->tsfn);
641     EXPECT_EQ(status, napi_ok);
642     AutoTsfn tsfn(callbackData->tsfn);
643     tsfn.Acquire();
644     g_receiveCnt = 0;
645 
646     status =
647         napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate,
648             true);
649     EXPECT_EQ(status, napi_ok);
650 
651     std::thread([](napi_env env, void* data) {
652         CallbackData* callbackData = (CallbackData*)data;
653         AutoTsfn tsfn(callbackData->tsfn);
654         CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_immediate);
655         CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_high);
656         CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_low);
657         CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_idle);
658         tsfn.CancelRelease();
659     }, env, callbackData).join();
660 }
661 
CallThreadSafeFuncWithCtx(void * context,napi_task_priority priority)662 static void CallThreadSafeFuncWithCtx(void* context, napi_task_priority priority)
663 {
664     CallbackData* callbackData = (CallbackData*)context;
665     AutoTsfn autoTsfn(callbackData->tsfn);
666     char *testData = (char *)malloc(DATA_LENGTH);
667     if (testData == nullptr) {
668         return;
669     }
670     memset_s(testData, DATA_LENGTH, 0, DATA_LENGTH);
671     if (priority == napi_priority_immediate) {
672         strcpy_s(testData, DATA_LENGTH, "hello world from A");
673     } else if (priority == napi_priority_high) {
674         strcpy_s(testData, DATA_LENGTH, "hello world from B");
675     } else if (priority == napi_priority_low) {
676         strcpy_s(testData, DATA_LENGTH, "hello world from C");
677     } else if (priority == napi_priority_idle) {
678         strcpy_s(testData, DATA_LENGTH, "hello world from D");
679     }
680     autoTsfn.Acquire();
681     callbackData->taskSize++;
682     auto status = napi_call_threadsafe_function_with_priority(callbackData->tsfn, testData, priority, true);
683     if (status != napi_ok) {
684         autoTsfn.Release();
685     }
686     EXPECT_EQ(status, napi_ok);
687 }
688 
finalizeCallBackWithPriority(napi_env env,void * finalizeData,void * hint)689 static void finalizeCallBackWithPriority(napi_env env, void* finalizeData, void* hint)
690 {
691     CallbackData *callbackData = reinterpret_cast<CallbackData *>(finalizeData);
692 #if defined(ENABLE_EVENT_HANDLER)
693     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork *>(callbackData->tsfn);
694     EXPECT_EQ(callbackData->taskSize, safeAsyncWork->taskSize_);
695 #endif
696     StopCurrentRunner();
697     reinterpret_cast<NativeEngine*>(env)->SetApiVersion(callbackData->version);
698     delete callbackData;
699 }
700 
finalizeCallBackWithPriority01(napi_env env,void * finalizeData,void * hint)701 static void finalizeCallBackWithPriority01(napi_env env, void* finalizeData, void* hint)
702 {
703     CallbackData *callbackData = reinterpret_cast<CallbackData *>(finalizeData);
704 #if defined(ENABLE_EVENT_HANDLER)
705     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork *>(callbackData->tsfn);
706     EXPECT_NE(callbackData->taskSize, safeAsyncWork->taskSize_);
707 #endif
708     StopCurrentRunner();
709     reinterpret_cast<NativeEngine*>(env)->SetApiVersion(callbackData->version);
710     delete callbackData;
711 }
712 
CallJsWithDiffPriority01(napi_env env,napi_value jsCb,void * context,void * data)713 static void CallJsWithDiffPriority01(napi_env env, napi_value jsCb, void *context, void *data)
714 {
715     EXPECT_NE(env, nullptr);
716     auto ctx = reinterpret_cast<CallbackData *>(context);
717     g_receiveCnt++;
718     napi_release_threadsafe_function(ctx->tsfn, napi_tsfn_release);
719     if (g_receiveCnt == FIRST_RECEIVER) {
720         return;
721     }
722     // check data string
723     char *testData = reinterpret_cast<char *>(data);
724     EXPECT_NE(testData, nullptr) << "testData is nullptr";
725     int32_t ret = 0;
726     if (g_receiveCnt == SECOND_RECEIVER) {
727         ret = strcmp(testData, "hello world from A");
728     } else if (g_receiveCnt == THIRD_RECEIVER) {
729         ret = strcmp(testData, "hello world from B");
730     } else if (g_receiveCnt == FOURTH_RECEIVER) {
731         std::this_thread::sleep_for(std::chrono::seconds(1));
732         ret = strcmp(testData, "hello world from C");
733     } else if (g_receiveCnt == FIFTH_RECEIVER) {
734         ret = strcmp(testData, "hello world from D");
735     }
736     EXPECT_EQ(ret, 0) << "data is: " << testData << ", execute id: " << g_receiveCnt;
737     ctx->taskSize--;
738 }
739 
CallThreadSafeWithDiffPriorityTest01()740 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityTest01()
741 {
742     int32_t version = engine_->GetApiVersion();
743     engine_->SetApiVersion(API_VERSION_FIFTEEN);
744     napi_env env = (napi_env)engine_;
745     napi_value resourceName = 0;
746     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
747     CallbackData *callbackData = new CallbackData();
748     callbackData->version = version;
749 
750     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0,
751         1, callbackData, finalizeCallBackWithPriority01, callbackData, CallJsWithDiffPriority01, &callbackData->tsfn);
752     EXPECT_EQ(status, napi_ok);
753     AutoTsfn tsfn(callbackData->tsfn);
754     tsfn.Acquire();
755     g_receiveCnt = 0;
756     callbackData->taskSize++;
757     status =
758         napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate,
759             true);
760     EXPECT_EQ(status, napi_ok);
761 
762     std::thread([](napi_env env, void* data) {
763         CallbackData* callbackData = (CallbackData*)data;
764         AutoTsfn tsfn(callbackData->tsfn);
765         CallThreadSafeFuncWithCtx(data, napi_priority_immediate);
766         CallThreadSafeFuncWithCtx(data, napi_priority_high);
767         CallThreadSafeFuncWithCtx(data, napi_priority_low);
768         CallThreadSafeFuncWithCtx(data, napi_priority_idle);
769     }, env, callbackData).join();
770 }
771 
CallThreadSafeWithDiffPriorityTest02()772 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityTest02()
773 {
774     int32_t version = engine_->GetApiVersion();
775     engine_->SetApiVersion(API_VERSION_SIXTEEN);
776     napi_env env = (napi_env)engine_;
777     napi_value resourceName = 0;
778     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
779     CallbackData *callbackData = new CallbackData();
780     callbackData->version = version;
781 
782     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
783         0, 1, callbackData, finalizeCallBackWithPriority, callbackData, CallJsWithDiffPriority, &callbackData->tsfn);
784     EXPECT_EQ(status, napi_ok);
785     AutoTsfn tsfn(callbackData->tsfn);
786     tsfn.Acquire();
787     g_receiveCnt = 0;
788     callbackData->taskSize++;
789     status =
790         napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate,
791             true);
792     EXPECT_EQ(status, napi_ok);
793 
794     std::thread([](napi_env env, void* data) {
795         CallbackData* callbackData = (CallbackData*)data;
796         AutoTsfn tsfn(callbackData->tsfn);
797         CallThreadSafeFuncWithCtx(data, napi_priority_immediate);
798         CallThreadSafeFuncWithCtx(data, napi_priority_high);
799         CallThreadSafeFuncWithCtx(data, napi_priority_low);
800         CallThreadSafeFuncWithCtx(data, napi_priority_idle);
801         tsfn.CancelRelease();
802     }, env, callbackData).join();
803 }
804 
CallThreadSafeWithDiffPriorityMultipleThreadTest()805 void NapiThreadsafeTest::CallThreadSafeWithDiffPriorityMultipleThreadTest()
806 {
807     napi_env env = (napi_env)engine_;
808     napi_value resourceName = 0;
809     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
810     CallbackData *callbackData = new CallbackData();
811 
812     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
813         0, 1, callbackData, ThreadFanalize, callbackData, CallJsWithDiffPriority, &callbackData->tsfn);
814     EXPECT_EQ(status, napi_ok);
815 
816     g_receiveCnt = 1;
817 
818     uint32_t* queuedTasks = new uint32_t;
819     uint32_t* executedTasks = new uint32_t;
820     *queuedTasks = 0;
821     *executedTasks = 0;
822 
823     std::mutex taskMutex;
824     std::condition_variable taskExecute;
825 
826     auto runFunc = [callbackData, &executedTasks, &taskMutex, &taskExecute](const napi_env &env, int32_t threadIndex) {
827         AutoTsfn tsfn(callbackData->tsfn);
828 
829         if (threadIndex == SECOND_THREAD_INDEX) {
830             CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_immediate);
831         } else if (threadIndex == THIRD_THREAD_INDEX) {
832             CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_high);
833         } else if (threadIndex == FOURTH_THREAD_INDEX) {
834             CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_low);
835         } else if (threadIndex == FIFTH_THREAD_INDEX) {
836             CallThreadSafeFunc(callbackData->tsfn, tsfn, napi_priority_idle);
837         }
838         {
839             std::lock_guard<std::mutex> lock(taskMutex);
840             ++(*executedTasks);
841             taskExecute.notify_one();
842         }
843         tsfn.CancelRelease();
844     };
845 
846     for (int32_t index = 1; index < THREAD_SIZE; ++index) {
847         std::thread runThread = std::thread(runFunc, std::ref(env), index);
848         ++(*queuedTasks);
849         runThread.detach();
850     }
851 
852     std::unique_lock<std::mutex> lock(taskMutex);
853     while (*queuedTasks != *executedTasks) {
854         taskExecute.wait(lock, [queuedTasks, executedTasks] {
855             return *queuedTasks == *executedTasks;
856         });
857     }
858     std::cout << "post task finish, posted: " << *queuedTasks << ", executed: " << g_receiveCnt << std::endl;
859     AutoTsfn tsfn(callbackData->tsfn);
860 }
861 
862 /**
863  * @tc.name: ThreadsafeTest001
864  * @tc.desc: Test LoadModule Func.
865  * @tc.type: FUNC
866  * @tc.require: I5K6KF
867  */
868 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest001, testing::ext::TestSize.Level1)
869 {
870     HILOG_INFO("Threadsafe_Test_0100 start");
871     napi_env env = (napi_env)engine_;
872     napi_threadsafe_function tsFunc = nullptr;
873     napi_value resourceName = 0;
874 
875     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
876     g_mainTid = gettid();
877     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
878     g_finalData.id = FINAL_CB_DATA_TEST_ID;
879 
880     auto status = napi_create_threadsafe_function(env,
881                                                   nullptr,
882                                                   nullptr,
883                                                   resourceName,
884                                                   0,
885                                                   1,
886                                                   &g_finalData,
887                                                   TsFuncFinal,
888                                                   &g_jsData,
889                                                   TsFuncCallJs,
890                                                   &tsFunc);
891     EXPECT_EQ(status, napi_ok);
892 
893     if (uv_thread_create(&g_uvThread, TsFuncDataSourceThread, tsFunc) != 0) {
894         HILOG_ERROR("Failed to create uv thread!");
895     }
896 
897     HILOG_INFO("Threadsafe_Test_0100 end");
898 }
899 
900 /**
901  * @tc.name: ThreadsafeTest002
902  * @tc.desc: Test LoadModule Func.
903  * @tc.type: FUNC
904  * @tc.require: I5K6KF
905  */
906 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest002, testing::ext::TestSize.Level1)
907 {
908     HILOG_INFO("Threadsafe_Test_0200 start");
909 
910     // start secondary thread, block on full
911     TsFuncThreadInternal((napi_env)engine_, TsFuncCallJsMulti, g_uvTheads2, true, true);
912 
913     HILOG_INFO("Threadsafe_Test_0200 end");
914 }
915 
916 /**
917  * @tc.name: ThreadsafeTest003
918  * @tc.desc: Test threadsafe Func, no js.
919  * @tc.type: FUNC
920  * @tc.require: I5K6KF
921  */
922 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest003, testing::ext::TestSize.Level1)
923 {
924     HILOG_INFO("Threadsafe_Test_0300 start");
925 
926     // secondary thread, not block
927     TsFuncThreadInternal((napi_env)engine_, TsFuncCallJsMulti, g_uvTheads3, false, false);
928 
929     HILOG_INFO("Threadsafe_Test_0300 end");
930 }
931 
932 /**
933  * @tc.name: ThreadsafeTest004
934  * @tc.desc: Test napi_release_threadsafe_function, napi_tsfn_abort.
935  * @tc.type: FUNC
936  * @tc.require: I5K6KF
937  */
938 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest004, testing::ext::TestSize.Level1)
939 {
940     HILOG_INFO("Threadsafe_Test_0400 start");
941     napi_env env = (napi_env)engine_;
942     napi_threadsafe_function tsFunc = nullptr;
943     napi_value resourceName = 0;
944 
945     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
946     g_mainTid = gettid();
947     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
948     g_finalData.id = FINAL_CB_DATA_TEST_ID;
949 
950     auto status = napi_create_threadsafe_function(env,
951                                                   nullptr,
952                                                   nullptr,
953                                                   resourceName,
954                                                   0,
955                                                   10,
956                                                   &g_finalData,
957                                                   TsFuncFinalTest5,
958                                                   &g_jsData,
959                                                   TsFuncCallJs,
960                                                   &tsFunc);
961     EXPECT_EQ(status, napi_ok);
962     status = napi_release_threadsafe_function(tsFunc, napi_tsfn_abort);
963     EXPECT_EQ(status, napi_ok);
964     if (uv_thread_create(&g_uvThreadTest5, TsFuncDataSourceThreadAbort, tsFunc) != 0) {
965         HILOG_ERROR("Failed to create uv thread!");
966     }
967 
968     HILOG_INFO("Threadsafe_Test_0400 end");
969 }
970 
971 /**
972  * @tc.name: ThreadsafeTest005
973  * @tc.desc: Test initial_thread_count not enough.
974  * @tc.type: FUNC
975  * @tc.require: I5K6KF
976  */
977 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest005, testing::ext::TestSize.Level1)
978 {
979     HILOG_INFO("Threadsafe_Test_0500 start");
980     napi_env env = (napi_env)engine_;
981     napi_threadsafe_function tsFunc = nullptr;
982     napi_value resourceName = 0;
983     g_callSuccessCountJS = 0;
984     g_callSuccessCount = 0;
985     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
986     g_mainTid = gettid();
987     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
988     g_finalData.id = FINAL_CB_DATA_TEST_ID;
989 
990     auto status = napi_create_threadsafe_function(env,
991                                                   nullptr,
992                                                   nullptr,
993                                                   resourceName,
994                                                   0,
995                                                   2,
996                                                   &g_finalData,
997                                                   TsFuncFinalTotal,
998                                                   &g_jsData,
999                                                   TsFuncCallJsTwo,
1000                                                   &tsFunc);
1001     EXPECT_EQ(status, napi_ok);
1002     int threadCount = THREAD_COUNT_FOUR;
1003     acquireFlag = false;
1004 
1005     for (int i = 0; i < threadCount; i++) {
1006         if (uv_thread_create(&g_uvThreadTest6, TsFuncDataSourceThreadCountTotal, tsFunc) != 0) {
1007             HILOG_ERROR("Failed to create uv thread!");
1008         }
1009     }
1010 
1011     usleep(200 * 1000);
1012     EXPECT_EQ(g_callSuccessCount, SUCCESS_COUNT_JS_FOUR);
1013     HILOG_INFO("Threadsafe_Test_0500 end");
1014 }
1015 
1016 /**
1017  * @tc.name: ThreadsafeTest006
1018  * @tc.desc: Test initial_thread_count not enough but acquire.
1019  * @tc.type: FUNC
1020  * @tc.require: I5K6KF
1021  */
1022 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest006, testing::ext::TestSize.Level1)
1023 {
1024     HILOG_INFO("Threadsafe_Test_0600 start");
1025     napi_env env = (napi_env)engine_;
1026     napi_threadsafe_function tsFunc = nullptr;
1027     napi_value resourceName = 0;
1028     g_callSuccessCount = 0;
1029     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1030     g_mainTid = gettid();
1031     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1032     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1033 
1034     auto status = napi_create_threadsafe_function(env,
1035                                                   nullptr,
1036                                                   nullptr,
1037                                                   resourceName,
1038                                                   0,
1039                                                   1,
1040                                                   &g_finalData,
1041                                                   TsFuncFinalTotalFour,
1042                                                   &g_jsData,
1043                                                   TsFuncCallJsFour,
1044                                                   &tsFunc);
1045     EXPECT_EQ(status, napi_ok);
1046     int threadCount = THREAD_COUNT_FOUR;
1047     acquireFlag = true;
1048 
1049     for (int i = 0; i < threadCount; i++) {
1050         if (uv_thread_create(&g_uvThreadTest7, TsFuncDataSourceThreadCountTotal, tsFunc) != 0) {
1051             HILOG_ERROR("Failed to create uv thread!");
1052         }
1053     }
1054 
1055     usleep(200 * 1000);
1056     EXPECT_EQ(g_callSuccessCount, SUCCESS_COUNT_JS_FOUR);
1057     HILOG_INFO("Threadsafe_Test_0600 end");
1058 }
1059 
1060 /**
1061  * @tc.name: ThreadsafeTest007
1062  * @tc.desc: Test napi_ref_threadsafe_function.
1063  * @tc.type: FUNC
1064  * @tc.require: I5K6KF
1065  */
1066 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest007, testing::ext::TestSize.Level1)
1067 {
1068     HILOG_INFO("Threadsafe_Test_0700 start");
1069 
1070     napi_env env = (napi_env)engine_;
1071     napi_threadsafe_function tsFunc = nullptr;
1072     napi_value resourceName = 0;
1073 
1074     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1075     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1076     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1077 
1078     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1079         0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1080     EXPECT_EQ(status, napi_ok);
1081 
1082     status = napi_ref_threadsafe_function(env, tsFunc);
1083     EXPECT_EQ(status, napi_ok);
1084 
1085     HILOG_INFO("Threadsafe_Test_0700 end");
1086 }
1087 
1088 /**
1089  * @tc.name: ThreadsafeTest008
1090  * @tc.desc: Test napi_unref_threadsafe_function.
1091  * @tc.type: FUNC
1092  * @tc.require: I5K6KF
1093  */
1094 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest008, testing::ext::TestSize.Level1)
1095 {
1096     HILOG_INFO("Threadsafe_Test_0800 start");
1097     napi_env env = (napi_env)engine_;
1098     napi_threadsafe_function tsFunc = nullptr;
1099     napi_value resourceName = 0;
1100 
1101     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1102     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1103     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1104 
1105     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1106         0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1107     EXPECT_EQ(status, napi_ok);
1108 
1109     status = napi_unref_threadsafe_function(env, tsFunc);
1110     EXPECT_EQ(status, napi_ok);
1111 
1112     HILOG_INFO("Threadsafe_Test_0800 end");
1113 }
1114 
1115 /**
1116  * @tc.name: ThreadsafeTest009
1117  * @tc.desc: Test napi_ref_threadsafe_function and napi_unref_threadsafe_function.
1118  * @tc.type: FUNC
1119  * @tc.require: I5K6KF
1120  */
1121 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest009, testing::ext::TestSize.Level1)
1122 {
1123     HILOG_INFO("Threadsafe_Test_0900 start");
1124     napi_env env = (napi_env)engine_;
1125     napi_threadsafe_function tsFunc = nullptr;
1126     napi_value resourceName = 0;
1127 
1128     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1129     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1130     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1131 
1132     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1133         0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1134     EXPECT_EQ(status, napi_ok);
1135 
1136     status = napi_unref_threadsafe_function(env, tsFunc);
1137     EXPECT_EQ(status, napi_ok);
1138 
1139     status = napi_unref_threadsafe_function(env, tsFunc);
1140     EXPECT_EQ(status, napi_ok);
1141 
1142     HILOG_INFO("Threadsafe_Test_0900 end");
1143 }
1144 
1145 /**
1146  * @tc.name: ThreadsafeTest010
1147  * @tc.desc: Test napi_unref_threadsafe_function and napi_release_threadsafe_function.
1148  * @tc.type: FUNC
1149  * @tc.require: I5K6KF
1150  */
1151 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest010, testing::ext::TestSize.Level1)
1152 {
1153     HILOG_INFO("Threadsafe_Test_1000 start");
1154     napi_env env = (napi_env)engine_;
1155     napi_threadsafe_function tsFunc = nullptr;
1156     napi_value resourceName = 0;
1157     napi_threadsafe_function_release_mode abort = napi_tsfn_abort;
1158 
1159     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1160     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1161     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1162 
1163     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1164         0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1165     EXPECT_EQ(status, napi_ok);
1166 
1167     status = napi_unref_threadsafe_function(env, tsFunc);
1168     EXPECT_EQ(status, napi_ok);
1169 
1170     status = napi_release_threadsafe_function(tsFunc, abort);
1171     EXPECT_EQ(status, napi_ok);
1172 
1173     HILOG_INFO("Threadsafe_Test_1000 end");
1174 }
1175 
1176 /**
1177  * @tc.name: ThreadsafeTest011
1178  * @tc.desc: Test napi_ref_threadsafe_function and napi_release_threadsafe_function.
1179  * @tc.type: FUNC
1180  * @tc.require: I5K6KF
1181  */
1182 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest011, testing::ext::TestSize.Level1)
1183 {
1184     HILOG_INFO("Threadsafe_Test_1100 start");
1185 
1186     napi_env env = (napi_env)engine_;
1187     napi_threadsafe_function tsFunc = nullptr;
1188     napi_value resourceName = 0;
1189     napi_threadsafe_function_release_mode abort = napi_tsfn_abort;
1190 
1191     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1192     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1193     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1194 
1195     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1196         0, 1, &g_finalData, TsFuncFinalCallback, &g_jsData, TsFuncCallJsFour, &tsFunc);
1197     EXPECT_EQ(status, napi_ok);
1198 
1199     status = napi_ref_threadsafe_function(env, tsFunc);
1200     EXPECT_EQ(status, napi_ok);
1201 
1202     status = napi_release_threadsafe_function(tsFunc, abort);
1203     EXPECT_EQ(status, napi_ok);
1204 
1205     HILOG_INFO("Threadsafe_Test_1100 end");
1206 }
1207 
1208 /**
1209  * @tc.name: ThreadsafeWithPriorityArgsCheckTest001
1210  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1211  * @tc.type: FUNC
1212  * @tc.require: I99QUH
1213  */
1214 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest001, testing::ext::TestSize.Level1)
1215 {
1216     HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest001 start");
1217     auto status =
1218         napi_call_threadsafe_function_with_priority(nullptr, nullptr, napi_priority_immediate, true);
1219     EXPECT_EQ(status, napi_invalid_arg);
1220     HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest001 end");
1221 }
1222 
1223 /**
1224  * @tc.name: ThreadsafeWithPriorityArgsCheckTest002
1225  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1226  * @tc.type: FUNC
1227  * @tc.require: I99QUH
1228  */
1229 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityArgsCheckTest002, testing::ext::TestSize.Level1)
1230 {
1231     HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest002 start");
1232     napi_env env = (napi_env)engine_;
1233     napi_value resourceName = 0;
1234     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1235     CallbackData *callbackData = new CallbackData();
1236     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1237         0, 1, callbackData, nullptr, callbackData, CallJs, &callbackData->tsfn);
1238     EXPECT_EQ(status, napi_ok);
1239     status =
1240         napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr,
1241             static_cast<napi_task_priority>(INVALID_NAPI_THREAD_SAFE_PRIORITY), true);
1242     EXPECT_NE(status, napi_ok);
1243     delete callbackData;
1244     HILOG_INFO("ThreadsafeWithPriorityArgsCheckTest002 end");
1245 }
1246 
1247 /**
1248  * @tc.name: ThreadsafeWithPriorityTest001
1249  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1250  * @tc.type: FUNC
1251  * @tc.require: I99QUH
1252  */
1253 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest001, testing::ext::TestSize.Level1)
1254 {
1255     HILOG_INFO("ThreadsafeWithPriorityTest001 start");
1256     g_isTailA = true;
1257     g_isTailB = true;
__anonf2fb28fd0702() 1258     auto task = [test = this]() {
1259         test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
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("ThreadsafeWithPriorityTest001 end");
1267 }
1268 
1269 /**
1270  * @tc.name: ThreadsafeWithPriorityTest002
1271  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1272  * @tc.type: FUNC
1273  * @tc.require: I99QUH
1274  */
1275 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest002, testing::ext::TestSize.Level1)
1276 {
1277     HILOG_INFO("ThreadsafeWithPriorityTest002 start");
1278     g_isTailA = false;
1279     g_isTailB = false;
__anonf2fb28fd0802() 1280     auto task = [test = this]() {
1281         test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
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("ThreadsafeWithPriorityTest002 end");
1289 }
1290 
1291 /**
1292  * @tc.name: ThreadsafeWithPriorityTest003
1293  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1294  * @tc.type: FUNC
1295  * @tc.require: I99QUH
1296  */
1297 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest003, testing::ext::TestSize.Level1)
1298 {
1299     HILOG_INFO("ThreadsafeWithPriorityTest003 start");
1300     g_isTailA = true;
1301     g_isTailB = false;
__anonf2fb28fd0902() 1302     auto task = [test = this]() {
1303         test->CallThreadSafeWithSamePriorityTest(napi_priority_immediate);
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("ThreadsafeWithPriorityTest003 end");
1311 }
1312 
1313 /**
1314  * @tc.name: ThreadsafeWithPriorityTest004
1315  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1316  * @tc.type: FUNC
1317  * @tc.require: I99QUH
1318  */
1319 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest004, testing::ext::TestSize.Level1)
1320 {
1321     HILOG_INFO("ThreadsafeWithPriorityTest004 start");
1322     g_isTailA = true;
1323     g_isTailB = true;
__anonf2fb28fd0a02() 1324     auto task = [test = this]() {
1325         test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1326     };
1327     EXPECT_NE(eventHandler_, nullptr);
1328     eventHandler_->PostTask(task);
1329     auto runner = eventHandler_->GetEventRunner();
1330     EXPECT_NE(runner, nullptr);
1331     runner->Run();
1332     HILOG_INFO("ThreadsafeWithPriorityTest004 end");
1333 }
1334 
1335 /**
1336  * @tc.name: ThreadsafeWithPriorityTest005
1337  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1338  * @tc.type: FUNC
1339  * @tc.require: I99QUH
1340  */
1341 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest005, testing::ext::TestSize.Level1)
1342 {
1343     HILOG_INFO("ThreadsafeWithPriorityTest005 start");
1344     g_isTailA = false;
1345     g_isTailB = false;
__anonf2fb28fd0b02() 1346     auto task = [test = this]() {
1347         test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1348     };
1349     EXPECT_NE(eventHandler_, nullptr);
1350     eventHandler_->PostTask(task);
1351     auto runner = eventHandler_->GetEventRunner();
1352     EXPECT_NE(runner, nullptr);
1353     runner->Run();
1354     HILOG_INFO("ThreadsafeWithPriorityTest005 end");
1355 }
1356 
1357 /**
1358  * @tc.name: ThreadsafeWithPriorityTest006
1359  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1360  * @tc.type: FUNC
1361  * @tc.require: I99QUH
1362  */
1363 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest006, testing::ext::TestSize.Level1)
1364 {
1365     HILOG_INFO("ThreadsafeWithPriorityTest006 start");
1366     g_isTailA = true;
1367     g_isTailB = false;
__anonf2fb28fd0c02() 1368     auto task = [test = this]() {
1369         test->CallThreadSafeWithSamePriorityTest(napi_priority_high);
1370     };
1371     EXPECT_NE(eventHandler_, nullptr);
1372     eventHandler_->PostTask(task);
1373     auto runner = eventHandler_->GetEventRunner();
1374     EXPECT_NE(runner, nullptr);
1375     runner->Run();
1376     HILOG_INFO("ThreadsafeWithPriorityTest006 end");
1377 }
1378 
1379 /**
1380  * @tc.name: ThreadsafeWithPriorityTest007
1381  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1382  * @tc.type: FUNC
1383  * @tc.require: I99QUH
1384  */
1385 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest007, testing::ext::TestSize.Level1)
1386 {
1387     HILOG_INFO("ThreadsafeWithPriorityTest007 start");
1388     g_isTailA = true;
1389     g_isTailB = true;
__anonf2fb28fd0d02() 1390     auto task = [test = this]() {
1391         test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1392     };
1393     EXPECT_NE(eventHandler_, nullptr);
1394     eventHandler_->PostTask(task);
1395     auto runner = eventHandler_->GetEventRunner();
1396     EXPECT_NE(runner, nullptr);
1397     runner->Run();
1398     HILOG_INFO("ThreadsafeWithPriorityTest007 end");
1399 }
1400 
1401 /**
1402  * @tc.name: ThreadsafeWithPriorityTest008
1403  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1404  * @tc.type: FUNC
1405  * @tc.require: I99QUH
1406  */
1407 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest008, testing::ext::TestSize.Level1)
1408 {
1409     HILOG_INFO("ThreadsafeWithPriorityTest008 start");
1410     g_isTailA = false;
1411     g_isTailB = false;
__anonf2fb28fd0e02() 1412     auto task = [test = this]() {
1413         test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1414     };
1415     EXPECT_NE(eventHandler_, nullptr);
1416     eventHandler_->PostTask(task);
1417     auto runner = eventHandler_->GetEventRunner();
1418     EXPECT_NE(runner, nullptr);
1419     runner->Run();
1420     HILOG_INFO("ThreadsafeWithPriorityTest008 end");
1421 }
1422 
1423 /**
1424  * @tc.name: ThreadsafeWithPriorityTest009
1425  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1426  * @tc.type: FUNC
1427  * @tc.require: I99QUH
1428  */
1429 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest009, testing::ext::TestSize.Level1)
1430 {
1431     HILOG_INFO("ThreadsafeWithPriorityTest009 start");
1432     g_isTailA = true;
1433     g_isTailB = false;
__anonf2fb28fd0f02() 1434     auto task = [test = this]() {
1435         test->CallThreadSafeWithSamePriorityTest(napi_priority_low);
1436     };
1437     EXPECT_NE(eventHandler_, nullptr);
1438     eventHandler_->PostTask(task);
1439     auto runner = eventHandler_->GetEventRunner();
1440     EXPECT_NE(runner, nullptr);
1441     runner->Run();
1442     HILOG_INFO("ThreadsafeWithPriorityTest009 end");
1443 }
1444 
1445 
1446 /**
1447  * @tc.name: ThreadsafeWithPriorityTest010
1448  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1449  * @tc.type: FUNC
1450  * @tc.require: I99QUH
1451  */
1452 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest010, testing::ext::TestSize.Level1)
1453 {
1454     HILOG_INFO("ThreadsafeWithPriorityTest010 start");
1455     g_isTailA = true;
1456     g_isTailB = true;
__anonf2fb28fd1002() 1457     auto task = [test = this]() {
1458         test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1459     };
1460     EXPECT_NE(eventHandler_, nullptr);
1461     eventHandler_->PostTask(task);
1462     auto runner = eventHandler_->GetEventRunner();
1463     EXPECT_NE(runner, nullptr);
1464     runner->Run();
1465     HILOG_INFO("ThreadsafeWithPriorityTest010 end");
1466 }
1467 
1468 /**
1469  * @tc.name: ThreadsafeWithPriorityTest011
1470  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1471  * @tc.type: FUNC
1472  * @tc.require: I99QUH
1473  */
1474 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest011, testing::ext::TestSize.Level1)
1475 {
1476     HILOG_INFO("ThreadsafeWithPriorityTest005 start");
1477     g_isTailA = false;
1478     g_isTailB = false;
__anonf2fb28fd1102() 1479     auto task = [test = this]() {
1480         test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1481     };
1482     EXPECT_NE(eventHandler_, nullptr);
1483     eventHandler_->PostTask(task);
1484     auto runner = eventHandler_->GetEventRunner();
1485     EXPECT_NE(runner, nullptr);
1486     runner->Run();
1487     HILOG_INFO("ThreadsafeWithPriorityTest011 end");
1488 }
1489 
1490 /**
1491  * @tc.name: ThreadsafeWithPriorityTest012
1492  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1493  * @tc.type: FUNC
1494  * @tc.require: I99QUH
1495  */
1496 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest012, testing::ext::TestSize.Level1)
1497 {
1498     HILOG_INFO("ThreadsafeWithPriorityTest012 start");
1499     g_isTailA = true;
1500     g_isTailB = false;
__anonf2fb28fd1202() 1501     auto task = [test = this]() {
1502         test->CallThreadSafeWithSamePriorityTest(napi_priority_idle);
1503     };
1504     EXPECT_NE(eventHandler_, nullptr);
1505     eventHandler_->PostTask(task);
1506     auto runner = eventHandler_->GetEventRunner();
1507     EXPECT_NE(runner, nullptr);
1508     runner->Run();
1509     HILOG_INFO("ThreadsafeWithPriorityTest012 end");
1510 }
1511 
1512 /**
1513  * @tc.name: ThreadsafeWithPriorityTest013
1514  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1515  * @tc.type: FUNC
1516  * @tc.require: I99QUH
1517  */
1518 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest013, testing::ext::TestSize.Level1)
1519 {
1520     HILOG_INFO("ThreadsafeWithPriorityTest013 start");
__anonf2fb28fd1302() 1521     auto task = [test = this]() {
1522         test->CallThreadSafeWithDiffPriorityTest();
1523     };
1524     EXPECT_NE(eventHandler_, nullptr);
1525     eventHandler_->PostTask(task);
1526     auto runner = eventHandler_->GetEventRunner();
1527     EXPECT_NE(runner, nullptr);
1528     runner->Run();
1529     HILOG_INFO("ThreadsafeWithPriorityTest013 end");
1530 }
1531 
1532 /**
1533  * @tc.name: ThreadsafeWithPriorityTest014
1534  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1535  * @tc.type: FUNC
1536  * @tc.require: I99QUH
1537  */
1538 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest014, testing::ext::TestSize.Level1)
1539 {
1540     HILOG_INFO("ThreadsafeWithPriorityTest014 start");
__anonf2fb28fd1402() 1541     auto task = [test = this]() {
1542         test->CallThreadSafeWithDiffPriorityMultipleThreadTest();
1543     };
1544     EXPECT_NE(eventHandler_, nullptr);
1545     eventHandler_->PostTask(task);
1546     auto runner = eventHandler_->GetEventRunner();
1547     EXPECT_NE(runner, nullptr);
1548     runner->Run();
1549     HILOG_INFO("ThreadsafeWithPriorityTest014 end");
1550 }
1551 
1552 /**
1553  * @tc.name: ThreadsafeWithPriorityTest015
1554  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1555  * @tc.type: FUNC
1556  * @tc.require: I99QUH
1557  */
1558 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest015, testing::ext::TestSize.Level1)
1559 {
1560     HILOG_INFO("ThreadsafeWithPriorityTest015 start");
__anonf2fb28fd1502() 1561     auto task = [test = this]() {
1562         test->CallThreadSafeWithDiffPriorityTest01();
1563     };
1564     EXPECT_NE(eventHandler_, nullptr);
1565     eventHandler_->PostTask(task);
1566     auto runner = eventHandler_->GetEventRunner();
1567     EXPECT_NE(runner, nullptr);
1568     runner->Run();
1569     HILOG_INFO("ThreadsafeWithPriorityTest015 end");
1570 }
1571 
1572 /**
1573  * @tc.name: ThreadsafeWithPriorityTest016
1574  * @tc.desc: Test napi_call_threadsafe_function_with_priority.
1575  * @tc.type: FUNC
1576  * @tc.require: I99QUH
1577  */
1578 HWTEST_F(NapiThreadsafeTest, ThreadsafeWithPriorityTest016, testing::ext::TestSize.Level1)
1579 {
1580     HILOG_INFO("ThreadsafeWithPriorityTest016 start");
__anonf2fb28fd1602() 1581     auto task = [test = this]() {
1582         test->CallThreadSafeWithDiffPriorityTest02();
1583     };
1584     EXPECT_NE(eventHandler_, nullptr);
1585     eventHandler_->PostTask(task);
1586     auto runner = eventHandler_->GetEventRunner();
1587     EXPECT_NE(runner, nullptr);
1588     runner->Run();
1589     HILOG_INFO("ThreadsafeWithPriorityTest016 end");
1590 }
1591 
1592 /**
1593  * @tc.name: ThreadsafeTest012
1594  * @tc.desc: Test LoadModule Func, call napi_call_threadsafe_function in callback.
1595  * @tc.type: FUNC
1596  * @tc.require: I5K6KF
1597  */
1598 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest012, testing::ext::TestSize.Level1)
1599 {
1600     HILOG_INFO("Threadsafe_Test_1200 start");
1601     napi_env env = (napi_env)engine_;
1602     napi_threadsafe_function tsFunc = nullptr;
1603     napi_value resourceName = 0;
1604 
1605     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1606     g_mainTid = gettid();
1607     g_jsData.id = CALL_JS_CB_DATA_TEST_ID;
1608     g_finalData.id = FINAL_CB_DATA_TEST_ID;
1609 
1610     auto status = napi_create_threadsafe_function(env,
1611                                                   nullptr,
1612                                                   nullptr,
1613                                                   resourceName,
1614                                                   0,
1615                                                   1,
1616                                                   &g_finalData,
1617                                                   TsFuncFinal,
1618                                                   &g_jsData,
1619                                                   TsFuncCallJsWithNewCall,
1620                                                   &tsFunc);
1621     EXPECT_EQ(status, napi_ok);
1622 
1623     if (uv_thread_create(
1624             &g_uvThread,
__anonf2fb28fd1702(void *data) 1625             [](void *data) {
1626                 napi_threadsafe_function func = (napi_threadsafe_function)data;
1627                 auto status = napi_call_threadsafe_function(func, data, napi_tsfn_nonblocking);
1628                 EXPECT_EQ(status, napi_ok);
1629             },
1630             tsFunc) != 0) {
1631         HILOG_ERROR("Failed to create uv thread!");
1632     }
1633 
1634     HILOG_INFO("Threadsafe_Test_1200 end");
1635 }
1636 
1637 
1638 struct CallbackCountData {
1639     napi_threadsafe_function tsfn;
1640     napi_async_work work;
1641     int callThreadsafeCount;
1642     int callbackCount;
1643 };
1644 
callJSCallBack(napi_env env,napi_value tsfn_cb,void * context,void * data)1645 static void callJSCallBack(napi_env env, napi_value tsfn_cb, void* context, void* data)
1646 {
1647     CallbackCountData *callbackData = reinterpret_cast<CallbackCountData *>(data);
1648     if (callbackData->callThreadsafeCount == INT_ONE) {
1649         callbackData->callThreadsafeCount++;
1650         napi_call_threadsafe_function(callbackData->tsfn, (void *)callbackData, napi_tsfn_nonblocking);
1651         napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
1652     }
1653     callbackData->callbackCount++;
1654 }
1655 
finalizeCallBack(napi_env env,void * finalizeData,void * hint)1656 static void finalizeCallBack(napi_env env, void* finalizeData, void* hint)
1657 {
1658     CallbackCountData *callbackData = reinterpret_cast<CallbackCountData *>(finalizeData);
1659     EXPECT_EQ(callbackData->callbackCount, INT_TWO);
1660     delete callbackData;
1661 }
1662 
executeWork(napi_env env,void * data)1663 static void executeWork(napi_env env, void *data)
1664 {
1665     CallbackCountData *callbackData = reinterpret_cast<CallbackCountData *>(data);
1666     callbackData->callThreadsafeCount++;
1667     napi_call_threadsafe_function(callbackData->tsfn, (void *)callbackData, napi_tsfn_nonblocking);
1668 }
1669 
1670 HWTEST_F(NapiThreadsafeTest, ThreadsafeTest013, testing::ext::TestSize.Level1)
1671 {
1672     HILOG_INFO("ThreadsafeTest013 start");
1673     napi_env env = (napi_env)engine_;
1674     CallbackCountData *callbackData = new CallbackCountData();
1675     callbackData->callThreadsafeCount = 0;
1676     callbackData->callbackCount = 0;
1677     napi_value resourceName = 0;
1678     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1679 
1680     auto status = napi_create_threadsafe_function(env, nullptr, nullptr, resourceName,
1681         0, 1, callbackData, finalizeCallBack, callbackData, callJSCallBack, &callbackData->tsfn);
1682     EXPECT_EQ(status, napi_ok);
1683 
1684     napi_create_async_work(env, nullptr, resourceName, executeWork,
__anonf2fb28fd1802(napi_env env, napi_status status, void* data) 1685         [](napi_env env, napi_status status, void* data) {
1686             CallbackCountData *callbackData = reinterpret_cast<CallbackCountData *>(data);
1687             napi_delete_async_work(env, callbackData->work);
1688         },
1689         callbackData, &callbackData->work);
1690     napi_queue_async_work(env, callbackData->work);
1691     HILOG_INFO("ThreadsafeTest013 end");
1692 }