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