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