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