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