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