1 /*
2  * Copyright (c) 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 "napi/native_api.h"
19 #include "napi/native_node_api.h"
20 #include "sequence_runner.h"
21 #include "task.h"
22 #include "task_group.h"
23 #include "task_manager.h"
24 #include "taskpool.h"
25 #include "utils.h"
26 #include "uv.h"
27 #include "worker.h"
28 
29 namespace Commonlibrary::Concurrent::TaskPoolModule {
30 
31 static constexpr uint32_t MAX_TIMEOUT_TIME = 600000;
32 static constexpr uint32_t FINSHED_TASK_ = 5;
33 static constexpr uint32_t TASK_NUMS_ = 7;
34 static constexpr uint64_t UINT64_ZERO_ = 0;
35 static constexpr uint32_t UINT32_ZERO_ = 0;
36 static constexpr uint32_t UINT32_ONE_ = 1;
37 static constexpr size_t SIZE_TWO_ = 2;
38 static constexpr size_t SIZE_THREE_ = 3;
39 
CreateReference(napi_env env)40 napi_ref CreateReference(napi_env env)
41 {
42     napi_value obj = NapiHelper::CreateObject(env);
43     return NapiHelper::CreateReference(env, obj, 1);
44 }
45 
CreateSendableClass(napi_env env)46 napi_value SendableUtils::CreateSendableClass(napi_env env)
47 {
48     auto constructor = [](napi_env env, napi_callback_info info) -> napi_value {
49         napi_value thisVar = nullptr;
50         napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
51         return thisVar;
52     };
53 
54     napi_property_descriptor props[] = {
55         DECLARE_NAPI_FUNCTION("foo", Foo),
56         DECLARE_NAPI_FUNCTION("bar", Bar),
57     };
58 
59     napi_value sendableClass = nullptr;
60     napi_define_sendable_class(env, "SendableClass", NAPI_AUTO_LENGTH, constructor, nullptr,
61                                sizeof(props) / sizeof(props[0]), props, nullptr, &sendableClass);
62     return sendableClass;
63 }
64 
CreateSendableInstance(napi_env env)65 napi_value SendableUtils::CreateSendableInstance(napi_env env)
66 {
67     napi_value cls = SendableUtils::CreateSendableClass(env);
68     napi_value instance = nullptr;
69     napi_new_instance(env, cls, 0, nullptr, &instance);
70     return instance;
71 }
72 
Foo(napi_env env,napi_callback_info info)73 napi_value SendableUtils::Foo(napi_env env, napi_callback_info info)
74 {
75     return nullptr;
76 }
77 
Bar(napi_env env,napi_callback_info info)78 napi_value SendableUtils::Bar(napi_env env, napi_callback_info info)
79 {
80     return nullptr;
81 }
82 
IsConcurrent(napi_env env,napi_value argv[],size_t argc)83 napi_value NativeEngineTest::IsConcurrent(napi_env env, napi_value argv[], size_t argc)
84 {
85     std::string funcName = "IsConcurrent";
86     napi_value cb = nullptr;
87     napi_value result = nullptr;
88     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::IsConcurrent, nullptr, &cb);
89     napi_call_function(env, nullptr, cb, argc, argv, &result);
90     return result;
91 }
92 
GetTaskPoolInfo(napi_env env,napi_value argv[],size_t argc)93 napi_value NativeEngineTest::GetTaskPoolInfo(napi_env env, napi_value argv[], size_t argc)
94 {
95     std::string funcName = "GetTaskPoolInfo";
96     napi_value cb = nullptr;
97     napi_value result = nullptr;
98     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::GetTaskPoolInfo, nullptr, &cb);
99     napi_call_function(env, nullptr, cb, argc, argv, &result);
100     return result;
101 }
102 
TerminateTask(napi_env env,napi_value argv[],size_t argc)103 napi_value NativeEngineTest::TerminateTask(napi_env env, napi_value argv[], size_t argc)
104 {
105     std::string funcName = "TerminateTask";
106     napi_value cb = nullptr;
107     napi_value result = nullptr;
108     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::TerminateTask, nullptr, &cb);
109     napi_call_function(env, nullptr, cb, argc, argv, &result);
110     return result;
111 }
112 
Execute(napi_env env,napi_value argv[],size_t argc)113 napi_value NativeEngineTest::Execute(napi_env env, napi_value argv[], size_t argc)
114 {
115     std::string funcName = "Execute";
116     napi_value cb = nullptr;
117     napi_value result = nullptr;
118     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::Execute, nullptr, &cb);
119     napi_call_function(env, nullptr, cb, argc, argv, &result);
120     return result;
121 }
122 
ExecuteDelayed(napi_env env,napi_value argv[],size_t argc)123 napi_value NativeEngineTest::ExecuteDelayed(napi_env env, napi_value argv[], size_t argc)
124 {
125     std::string funcName = "ExecuteDelayed";
126     napi_value cb = nullptr;
127     napi_value result = nullptr;
128     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::ExecuteDelayed, nullptr, &cb);
129     napi_call_function(env, nullptr, cb, argc, argv, &result);
130     return result;
131 }
132 
Cancel(napi_env env,napi_value argv[],size_t argc)133 napi_value NativeEngineTest::Cancel(napi_env env, napi_value argv[], size_t argc)
134 {
135     std::string funcName = "Cancel";
136     napi_value cb = nullptr;
137     napi_value result = nullptr;
138     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::Cancel, nullptr, &cb);
139     napi_call_function(env, nullptr, cb, argc, argv, &result);
140     return result;
141 }
142 
TaskGroupDestructor(napi_env env,void * data)143 void NativeEngineTest::TaskGroupDestructor(napi_env env, void* data)
144 {
145     void* hint = nullptr;
146     TaskGroup::TaskGroupDestructor(env, data, hint);
147 }
148 
SequenceRunnerDestructor(napi_env env,void * data)149 void NativeEngineTest::SequenceRunnerDestructor(napi_env env, void* data)
150 {
151     void* hint = nullptr;
152     SequenceRunner::SequenceRunnerDestructor(env, data, hint);
153 }
154 
ExecutePeriodically(napi_env env,napi_value argv[],size_t argc)155 napi_value NativeEngineTest::ExecutePeriodically(napi_env env, napi_value argv[], size_t argc)
156 {
157     std::string funcName = "ExecutePeriodically";
158     napi_value cb = nullptr;
159     napi_value result = nullptr;
160     napi_create_function(env, funcName.c_str(), funcName.size(), TaskPool::ExecutePeriodically, nullptr, &cb);
161     napi_call_function(env, nullptr, cb, argc, argv, &result);
162     return result;
163 }
164 
ExecuteGroup(napi_env env,napi_value taskGroup)165 napi_value NativeEngineTest::ExecuteGroup(napi_env env, napi_value taskGroup)
166 {
167     return TaskPool::ExecuteGroup(env, taskGroup, Priority::DEFAULT);
168 }
169 
DelayTask(uv_timer_t * handle)170 void NativeEngineTest::DelayTask(uv_timer_t* handle)
171 {
172     TaskPool::DelayTask(handle);
173 }
174 
PeriodicTaskCallback(uv_timer_t * handle)175 void NativeEngineTest::PeriodicTaskCallback(uv_timer_t* handle)
176 {
177     TaskPool::PeriodicTaskCallback(handle);
178 }
179 
UpdateGroupInfoByResult(napi_env env,uv_timer_t * handle,napi_value res,bool success)180 void NativeEngineTest::UpdateGroupInfoByResult(napi_env env, uv_timer_t* handle, napi_value res, bool success)
181 {
182     Task* task = reinterpret_cast<Task*>(handle->data);
183     TaskPool::UpdateGroupInfoByResult(env, task, res, success);
184 }
185 
TryTriggerExpand()186 void NativeEngineTest::TryTriggerExpand()
187 {
188     TaskManager& taskManager = TaskManager::GetInstance();
189     taskManager.isHandleInited_ = false;
190     taskManager.TryTriggerExpand();
191     taskManager.isHandleInited_ = true;
192     taskManager.needChecking_ = false;
193 }
194 
CheckForBlockedWorkers(napi_env env)195 void NativeEngineTest::CheckForBlockedWorkers(napi_env env)
196 {
197     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
198     worker->workerEnv_ = nullptr;
199     TaskManager& taskManager = TaskManager::GetInstance();
200     taskManager.workers_.clear();
201     taskManager.workers_.insert(worker);
202     taskManager.GetThreadInfos(env);
203 
204     worker->workerEnv_ = env;
205     worker->state_ = WorkerState::RUNNING;
206     worker->startTime_ = ConcurrentHelper::GetMilliseconds() - MAX_TIMEOUT_TIME;
207     worker->idleState_ = true;
208     taskManager.CheckForBlockedWorkers();
209 
210     worker->state_ = WorkerState::RUNNING;
211     worker->startTime_ = ConcurrentHelper::GetMilliseconds() - MAX_TIMEOUT_TIME;
212     worker->idleState_ = false;
213     worker->hasLongTask_ = true;
214     taskManager.CheckForBlockedWorkers();
215 
216     worker->state_ = WorkerState::RUNNING;
217     worker->startTime_ = ConcurrentHelper::GetMilliseconds() - MAX_TIMEOUT_TIME;
218     worker->idleState_ = false;
219     worker->hasLongTask_ = false;
220     taskManager.idleWorkers_.insert(worker);
221     taskManager.CheckForBlockedWorkers();
222     taskManager.timeoutWorkers_.clear();
223 }
224 
foo(const uv_async_t * req)225 void NativeEngineTest::foo(const uv_async_t* req)
226 {
227     return;
228 }
229 
TriggerShrink(napi_env env)230 void NativeEngineTest::TriggerShrink(napi_env env)
231 {
232     uint32_t step = 1;
233     TaskManager& taskManager = TaskManager::GetInstance();
234     taskManager.idleWorkers_.clear();
235     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
236     worker->workerEnv_ = env;
237     taskManager.idleWorkers_.insert(worker);
238 
239     taskManager.freeList_.emplace_back(worker);
240     worker->state_ = WorkerState::RUNNING;
241     taskManager.TriggerShrink(step);
242 
243     taskManager.idleWorkers_.clear();
244     taskManager.idleWorkers_.insert(worker);
245     taskManager.freeList_.emplace_back(worker);
246     worker->idlePoint_ = ConcurrentHelper::GetMilliseconds();
247     worker->state_ = WorkerState::IDLE;
248     worker->hasLongTask_ = false;
249     taskManager.TriggerShrink(step);
250 
251     taskManager.idleWorkers_.clear();
252     taskManager.idleWorkers_.insert(worker);
253     taskManager.freeList_.emplace_back(worker);
254     worker->idlePoint_ = ConcurrentHelper::GetMilliseconds() - MAX_TIMEOUT_TIME;
255     worker->state_ = WorkerState::IDLE;
256     worker->hasLongTask_ = false;
257     uv_loop_t* loop = worker->GetWorkerLoop();
258     ConcurrentHelper::UvHandleInit(loop, worker->clearWorkerSignal_, NativeEngineTest::foo, worker);
259     taskManager.TriggerShrink(step);
260     taskManager.idleWorkers_.clear();
261     taskManager.globalEnableFfrtFlag_ = false;
262 }
263 
NotifyShrink(napi_env env)264 void NativeEngineTest::NotifyShrink(napi_env env)
265 {
266     uint32_t step = 1;
267     TaskManager& taskManager = TaskManager::GetInstance();
268     taskManager.workers_.clear();
269     taskManager.timeoutWorkers_.clear();
270 
271     Worker* worker1 = reinterpret_cast<Worker*>(WorkerConstructor(env));
272     Worker* worker2 = reinterpret_cast<Worker*>(WorkerConstructor(env));
273     worker1->workerEnv_ = env;
274     worker2->workerEnv_ = env;
275     uv_loop_t* loop1 = worker1->GetWorkerLoop();
276     ConcurrentHelper::UvHandleInit(loop1, worker1->clearWorkerSignal_, NativeEngineTest::foo, worker1);
277     uv_loop_t* loop2 = worker2->GetWorkerLoop();
278     ConcurrentHelper::UvHandleInit(loop2, worker2->clearWorkerSignal_, NativeEngineTest::foo, worker2);
279     taskManager.workers_.insert(worker1);
280     taskManager.workers_.insert(worker2);
281     taskManager.timeoutWorkers_.insert(worker1);
282     taskManager.timeoutWorkers_.insert(worker2);
283     taskManager.NotifyShrink(step);
284 
285     taskManager.workers_.clear();
286     taskManager.timeoutWorkers_.clear();
287     taskManager.workers_.insert(worker1);
288     taskManager.idleWorkers_.insert(nullptr);
289     taskManager.NotifyShrink(step);
290 
291     taskManager.idleWorkers_.clear();
292     taskManager.idleWorkers_.insert(worker2);
293     worker2->hasLongTask_ = true;
294     taskManager.NotifyShrink(step);
295 
296     worker2->hasLongTask_ = false;
297     worker2->hasExecuted_ = true;
298     taskManager.NotifyShrink(step);
299 
300     worker2->hasExecuted_ = false;
301     taskManager.workers_.clear();
302     taskManager.NotifyShrink(step);
303 }
304 
TryExpand(napi_env env)305 void NativeEngineTest::TryExpand(napi_env env)
306 {
307     TaskManager& taskManager = TaskManager::GetInstance();
308     taskManager.workers_.clear();
309     taskManager.timeoutWorkers_.clear();
310     taskManager.idleWorkers_.clear();
311     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
312     worker->workerEnv_ = env;
313     uv_loop_t* loop = worker->GetWorkerLoop();
314     ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_, NativeEngineTest::foo, worker);
315     taskManager.idleWorkers_.insert(worker);
316     taskManager.TryExpand();
317     taskManager.nonIdleTaskNum_ = 1;
318     taskManager.TryExpand();
319     taskManager.nonIdleTaskNum_ = 0;
320     taskManager.TryExpand();
321     taskManager.idleWorkers_.clear();
322     taskManager.suspend_ = true;
323     taskManager.TryExpand();
324 }
325 
CancelTask(napi_env env)326 void NativeEngineTest::CancelTask(napi_env env)
327 {
328     TaskManager& taskManager = TaskManager::GetInstance();
329     Task* task = new Task();
330     task->taskType_ = TaskType::COMMON_TASK;
331     task->taskId_ = reinterpret_cast<uint64_t>(task);
332     napi_value val = NapiHelper::CreateObject(env);
333     napi_ref ref = NapiHelper::CreateReference(env, val, 0);
334     task->taskRef_ = ref;
335     taskManager.StoreTask(task->taskId_, task);
336     task->taskState_ = ExecuteState::CANCELED;
337     taskManager.CancelTask(env, task->taskId_);
338 
339     uv_loop_t* loop = NapiHelper::GetLibUV(env);
340     task->timer_ = new uv_timer_t;
341     uv_timer_init(loop, task->timer_);
342     task->taskState_ = ExecuteState::RUNNING;
343     task->isPeriodicTask_ = true;
344     taskManager.CancelTask(env, task->taskId_);
345 
346     task->isPeriodicTask_ = false;
347     task->taskType_ = TaskType::SEQRUNNER_TASK;
348     taskManager.CancelTask(env, task->taskId_);
349 
350     task->taskState_ = ExecuteState::FINISHED;
351     taskManager.CancelTask(env, task->taskId_);
352 
353     TaskInfo* taskInfo = new TaskInfo();
354     task->taskState_ = ExecuteState::WAITING;
355     task->currentTaskInfo_ = taskInfo;
356     taskManager.CancelTask(env, task->taskId_);
357     taskManager.tasks_.clear();
358     delete task;
359 }
360 
NotifyWorkerIdle(napi_env env)361 void NativeEngineTest::NotifyWorkerIdle(napi_env env)
362 {
363     TaskManager& taskManager = TaskManager::GetInstance();
364     Task* task = new Task();
365     task->taskId_ = reinterpret_cast<uint64_t>(task);
366     taskManager.taskQueues_[Priority::DEFAULT]->EnqueueTaskId(task->taskId_);
367     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
368     worker->workerEnv_ = env;
369     uv_loop_t* loop = worker->GetWorkerLoop();
370     ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_, NativeEngineTest::foo, worker);
371     worker->state_ = WorkerState::BLOCKED;
372     taskManager.NotifyWorkerIdle(worker);
373     worker->state_ = WorkerState::IDLE;
374     taskManager.NotifyWorkerIdle(worker);
375     delete task;
376 }
377 
EnqueueTaskId(napi_env env)378 void NativeEngineTest::EnqueueTaskId(napi_env env)
379 {
380     TaskManager& taskManager = TaskManager::GetInstance();
381     Task* task = new Task();
382     task->taskId_ = reinterpret_cast<uint64_t>(task);
383     taskManager.StoreTask(task->taskId_, task);
384     napi_value obj = Helper::NapiHelper::CreateObject(env);
385     napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, obj, 1);
386     task->onEnqueuedCallBackInfo_ = new ListenerCallBackInfo(env, callbackRef, nullptr);
387     taskManager.EnqueueTaskId(task->taskId_);
388 
389     taskManager.workers_.clear();
390     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
391     worker->state_ = WorkerState::RUNNING;
392     taskManager.workers_.insert(worker);
393     taskManager.IsChooseIdle();
394     taskManager.workers_.clear();
395     Helper::NapiHelper::DeleteReference(env, callbackRef);
396     delete task;
397 }
398 
GetTaskByPriority(napi_env env)399 void NativeEngineTest::GetTaskByPriority(napi_env env)
400 {
401     TaskManager& taskManager = TaskManager::GetInstance();
402     Task* task = new Task();
403     task->taskId_ = reinterpret_cast<uint64_t>(task);
404     taskManager.StoreTask(task->taskId_, task);
405     auto& mediumTaskQueue = taskManager.taskQueues_[Priority::DEFAULT];
406     uint64_t id = mediumTaskQueue->DequeueTaskId();
407     while (id != 0) {
408         id = mediumTaskQueue->DequeueTaskId();
409     }
410     taskManager.EnqueueTaskId(task->taskId_);
411     std::set<uint64_t> set{task->taskId_};
412     taskManager.dependTaskInfos_.emplace(task->taskId_, std::move(set));
413     taskManager.GetTaskByPriority(mediumTaskQueue, Priority::DEFAULT);
414     taskManager.dependTaskInfos_.clear();
415     taskManager.tasks_.clear();
416     delete task;
417 }
418 
RestoreWorker(napi_env env)419 void NativeEngineTest::RestoreWorker(napi_env env)
420 {
421     TaskManager& taskManager = TaskManager::GetInstance();
422     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
423     taskManager.suspend_ = false;
424     worker->state_ = WorkerState::BLOCKED;
425     taskManager.RestoreWorker(worker);
426 
427     Task* task = new Task();
428     task->taskId_ = reinterpret_cast<uint64_t>(task);
429     taskManager.EnqueueTaskId(task->taskId_);
430     worker->state_ = WorkerState::IDLE;
431     worker->workerEnv_ = env;
432     uv_loop_t* loop = worker->GetWorkerLoop();
433     ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_, NativeEngineTest::foo, worker);
434     taskManager.RestoreWorker(worker);
435 }
436 
StoreDependentId(uint64_t taskId,uint64_t dependentId)437 void NativeEngineTest::StoreDependentId(uint64_t taskId, uint64_t dependentId)
438 {
439     TaskManager& taskManager = TaskManager::GetInstance();
440     std::set<uint64_t> set{ dependentId };
441     taskManager.dependTaskInfos_.emplace(taskId, std::move(set));
442 }
443 
StoreDependentTaskId(uint64_t taskId,uint64_t dependentId)444 void NativeEngineTest::StoreDependentTaskId(uint64_t taskId, uint64_t dependentId)
445 {
446     TaskManager& taskManager = TaskManager::GetInstance();
447     std::set<uint64_t> set{ dependentId };
448     taskManager.dependentTaskInfos_.emplace(taskId, std::move(set));
449 }
450 
StoreTaskDuration(uint64_t taskId)451 void NativeEngineTest::StoreTaskDuration(uint64_t taskId)
452 {
453     TaskManager& taskManager = TaskManager::GetInstance();
454     uint64_t durationId = taskId + MAX_TIMEOUT_TIME;
455     std::pair<uint64_t, uint64_t> durationData = std::make_pair(taskId, durationId);
456     taskManager.taskDurationInfos_.emplace(taskId, std::move(durationData));
457 }
458 
InitTaskManager(napi_env env)459 void NativeEngineTest::InitTaskManager(napi_env env)
460 {
461     napi_env taskEnv = nullptr;
462     napi_create_runtime(env, &taskEnv);
463     NativeEngine* taskEngine = reinterpret_cast<NativeEngine*>(taskEnv);
464     taskEngine->MarkTaskPoolThread();
465     TaskManager& taskManager = TaskManager::GetInstance();
466     taskManager.globalEnableFfrtFlag_ = true;
467     taskManager.InitTaskManager(taskEnv);
468     taskManager.DecreaseRefCount(env, 0);
469     napi_value exception = nullptr;
470     napi_get_and_clear_last_exception(env, &exception);
471 }
472 
NotifyDependencyTaskInfo(napi_env env)473 void NativeEngineTest::NotifyDependencyTaskInfo(napi_env env)
474 {
475     TaskManager& taskManager = TaskManager::GetInstance();
476     Task* task = new Task();
477     task->taskId_ = reinterpret_cast<uint64_t>(task);
478     task->env_ = env;
479     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
480     worker->workerEnv_ = env;
481     task->worker_ = worker;
482     uint64_t id = task->taskId_ + MAX_TIMEOUT_TIME;
483     std::set<uint64_t> set{ task->taskId_, id };
484     taskManager.dependentTaskInfos_.emplace(task->taskId_, std::move(set));
485     taskManager.NotifyDependencyTaskInfo(task->taskId_);
486     std::set<uint64_t> set1{ task->taskId_, id };
487     taskManager.dependentTaskInfos_.emplace(task->taskId_, std::move(set1));
488     taskManager.EnqueuePendingTaskInfo(0, Priority::DEFAULT);
489     taskManager.EnqueuePendingTaskInfo(id, Priority::DEFAULT);
490     taskManager.EnqueuePendingTaskInfo(task->taskId_, Priority::DEFAULT);
491     taskManager.NotifyDependencyTaskInfo(task->taskId_);
492     std::set<uint64_t> set2{ task->taskId_, id };
493     taskManager.dependentTaskInfos_.emplace(task->taskId_, std::move(set2));
494     taskManager.IsDependentByTaskId(task->taskId_);
495 }
496 
StoreTaskDependency(napi_env env)497 void NativeEngineTest::StoreTaskDependency(napi_env env)
498 {
499     TaskManager& taskManager = TaskManager::GetInstance();
500     Task* task = new Task();
501     task->taskId_ = reinterpret_cast<uint64_t>(task);
502     task->env_ = env;
503     Task* task1 = new Task();
504     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
505     task1->env_ = env;
506     Task* task2 = new Task();
507     task2->taskId_ = reinterpret_cast<uint64_t>(task1);
508     task2->env_ = env;
509     taskManager.dependTaskInfos_.clear();
510     uint64_t id1 = task->taskId_;
511     uint64_t id2 = task->taskId_ + MAX_TIMEOUT_TIME;
512     uint64_t id3 = task1->taskId_;
513     uint64_t id4 = task1->taskId_ + MAX_TIMEOUT_TIME;
514     uint64_t id5 = task2->taskId_;
515     uint64_t id6 = task2->taskId_ + MAX_TIMEOUT_TIME;
516     std::set<uint64_t> set{ id2, id3 };
517     taskManager.dependTaskInfos_.emplace(id1, std::move(set));
518     std::set<uint64_t> taskId{ id1, id2 };
519     taskManager.StoreTaskDependency(id3, taskId);
520     taskManager.StoreTaskDependency(id5, taskId);
521     std::set<uint64_t> set1{ id4, id5 };
522     taskManager.dependTaskInfos_.emplace(id3, std::move(set1));
523     taskManager.StoreTaskDependency(id1, taskId);
524     std::set<uint64_t> set2{ id6 };
525     std::set<uint64_t> set3{ id1 };
526     taskManager.dependTaskInfos_.emplace(id5, std::move(set3));
527     taskManager.StoreTaskDependency(id1, taskId);
528     taskManager.dependTaskInfos_.emplace(id5, std::move(set2));
529     taskManager.StoreTaskDependency(id1, taskId);
530     taskManager.dependTaskInfos_.clear();
531     napi_value exception = nullptr;
532     napi_get_and_clear_last_exception(env, &exception);
533 }
534 
RemoveTaskDependency(napi_env env)535 void NativeEngineTest::RemoveTaskDependency(napi_env env)
536 {
537     TaskManager& taskManager = TaskManager::GetInstance();
538     Task* task = new Task();
539     task->taskId_ = reinterpret_cast<uint64_t>(task);
540     uint64_t id = task->taskId_ + MAX_TIMEOUT_TIME;
541     Task* task1 = new Task();
542     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
543     uint64_t id2 = task1->taskId_ + MAX_TIMEOUT_TIME;
544     taskManager.dependTaskInfos_.clear();
545     std::set<uint64_t> set{ id };
546     taskManager.dependTaskInfos_.emplace(task->taskId_, std::move(set));
547     taskManager.RemoveTaskDependency(task->taskId_, task1->taskId_);
548     taskManager.RemoveTaskDependency(task->taskId_, id);
549     std::set<uint64_t> set2{ id };
550     taskManager.dependentTaskInfos_.emplace(task->taskId_, std::move(set2));
551     std::set<uint64_t> dependentTaskIdSet{ task->taskId_ };
552     taskManager.StoreDependentTaskInfo(dependentTaskIdSet, task1->taskId_);
553     taskManager.RemoveDependentTaskInfo(task->taskId_, id2);
554     taskManager.RemoveDependentTaskInfo(task->taskId_, id);
555     taskManager.GetTaskDependInfoToString(task1->taskId_);
556     taskManager.taskDurationInfos_.emplace(task->taskId_, std::make_pair(UINT64_ZERO_, task1->taskId_));
557     taskManager.StoreTaskDuration(task->taskId_, UINT64_ZERO_, UINT64_ZERO_);
558     taskManager.GetTaskDuration(task->taskId_, "");
559     taskManager.RemoveTaskDuration(task->taskId_);
560 }
561 
ReleaseTaskData(napi_env env)562 void NativeEngineTest::ReleaseTaskData(napi_env env)
563 {
564     TaskManager& taskManager = TaskManager::GetInstance();
565     Task* task = new Task();
566     task->taskId_ = reinterpret_cast<uint64_t>(task);
567     task->onResultSignal_ = nullptr;
568     task->taskType_ = TaskType::FUNCTION_TASK;
569     taskManager.StoreTask(task->taskId_, task);
570     taskManager.ReleaseTaskData(env, task);
571     task->taskType_ = TaskType::GROUP_FUNCTION_TASK;
572     taskManager.StoreTask(task->taskId_, task);
573     taskManager.ReleaseTaskData(env, task);
574     std::set<uint64_t> set{ task->taskId_ };
575     taskManager.dependTaskInfos_.emplace(task->taskId_, std::move(set));
576     task->taskType_ = TaskType::COMMON_TASK;
577     taskManager.StoreTask(task->taskId_, task);
578     taskManager.ReleaseTaskData(env, task);
579     Task* task1 = new Task();
580     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
581     task1->onEnqueuedCallBackInfo_ = new ListenerCallBackInfo(env, nullptr, nullptr);
582     task1->onStartExecutionCallBackInfo_ = new ListenerCallBackInfo(env, nullptr, nullptr);
583     task1->onExecutionFailedCallBackInfo_ = new ListenerCallBackInfo(env, nullptr, nullptr);
584     task1->onExecutionSucceededCallBackInfo_ = new ListenerCallBackInfo(env, nullptr, nullptr);
585     taskManager.ReleaseCallBackInfo(task1);
586     Task* task2 = new Task();
587     task2->taskId_ = reinterpret_cast<uint64_t>(task2);
588     task2->isMainThreadTask_ = true;
589     taskManager.ReleaseCallBackInfo(task2);
590     task2->isMainThreadTask_ = false;
591     taskManager.ReleaseCallBackInfo(task2);
592     auto loop = NapiHelper::GetLibUV(env);
593     ConcurrentHelper::UvHandleInit(loop, task->onStartExecutionSignal_, NativeEngineTest::foo, task2);
594     taskManager.ReleaseCallBackInfo(task2);
595 }
596 
CheckTask(napi_env env)597 void NativeEngineTest::CheckTask(napi_env env)
598 {
599     TaskManager& taskManager = TaskManager::GetInstance();
600     Task* task = new Task();
601     task->taskId_ = reinterpret_cast<uint64_t>(task);
602     Task* task1 = new Task();
603     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
604     taskManager.StoreTask(task->taskId_, task);
605     taskManager.CheckTask(task1->taskId_);
606 
607     TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
608     TaskGroup* group = new TaskGroup();
609     napi_value obj = NapiHelper::CreateObject(env);
610     napi_ref ref = NapiHelper::CreateReference(env, obj, 1);
611     group->groupRef_ = ref;
612     uint64_t groupId = reinterpret_cast<uint64_t>(group);
613     groupManager.StoreTaskGroup(groupId, nullptr);
614     groupManager.AddTask(groupId, nullptr, task->taskId_);
615     groupManager.taskGroups_.clear();
616     groupManager.StoreTaskGroup(groupId, group);
617     group->groupState_ = ExecuteState::CANCELED;
618     groupManager.CancelGroup(env, groupId);
619 
620     group->groupState_ = ExecuteState::WAITING;
621     groupManager.CancelGroup(env, groupId);
622 
623     GroupInfo* groupInfo = new GroupInfo();
624     groupInfo->finishedTaskNum = FINSHED_TASK_;
625     group->currentGroupInfo_ = groupInfo;
626     group->groupState_ = ExecuteState::NOT_FOUND;
627     groupManager.CancelGroup(env, groupId);
628 
629     group->groupState_ = ExecuteState::FINISHED;
630     groupManager.CancelGroup(env, groupId);
631 
632     group->groupState_ = ExecuteState::RUNNING;
633     group->taskNum_ = FINSHED_TASK_;
634     group->taskIds_.push_back(task->taskId_);
635     groupManager.CancelGroup(env, groupId);
636 
637     group->taskNum_ = TASK_NUMS_;
638     group->groupState_ = ExecuteState::WAITING;
639     napi_value resArr;
640     napi_create_array_with_length(env, group->taskIds_.size(), &resArr);
641     napi_ref arrRef = NapiHelper::CreateReference(env, resArr, 1);
642     groupInfo->resArr = arrRef;
643     napi_value promise = NapiHelper::CreatePromise(env, &groupInfo->deferred);
644     groupManager.CancelGroup(env, groupId);
645 }
646 
CancelGroupTask(napi_env env)647 void NativeEngineTest::CancelGroupTask(napi_env env)
648 {
649     TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
650     TaskManager& taskManager = TaskManager::GetInstance();
651     TaskGroup* group = new TaskGroup();
652     group->currentGroupInfo_ = new GroupInfo();
653     Task* task = new Task();
654     task->taskId_ = reinterpret_cast<uint64_t>(task);
655     taskManager.StoreTask(task->taskId_, task);
656     task->taskState_ = ExecuteState::RUNNING;
657     groupManager.CancelGroupTask(env, task->taskId_, group);
658     task->taskState_ = ExecuteState::WAITING;
659     groupManager.CancelGroupTask(env, task->taskId_, group);
660     task->taskState_ = ExecuteState::WAITING;
661     TaskInfo* taskInfo = new TaskInfo();
662     task->currentTaskInfo_ = taskInfo;
663     groupManager.CancelGroupTask(env, task->taskId_, group);
664 
665     Task* task1 = new Task();
666     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
667     SequenceRunner* seqRunner = new SequenceRunner();
668     uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
669     groupManager.StoreSequenceRunner(seqRunnerId, seqRunner);
670     groupManager.AddTaskToSeqRunner(seqRunnerId, task1);
671 }
672 
TriggerSeqRunner(napi_env env)673 void NativeEngineTest::TriggerSeqRunner(napi_env env)
674 {
675     TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
676     Task* task = new Task();
677     task->taskId_ = reinterpret_cast<uint64_t>(task);
678     Task* task1 = new Task();
679     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
680     SequenceRunner* seqRunner = new SequenceRunner();
681     uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
682     seqRunner->priority_ = Priority::DEFAULT;
683     task->seqRunnerId_ = seqRunnerId;
684     groupManager.StoreSequenceRunner(seqRunnerId, seqRunner);
685     seqRunner->isGlobalRunner_ = true;
686     bool res = groupManager.TriggerSeqRunner(env, task);
687     ASSERT_FALSE(res);
688     seqRunner->globalSeqRunnerRef_.emplace(env, CreateReference(env));
689     seqRunner->currentTaskId_ = task1->taskId_;
690     groupManager.TriggerSeqRunner(env, task);
691     seqRunner->isGlobalRunner_ = false;
692     seqRunner->seqRunnerRef_ = CreateReference(env);
693     seqRunner->currentTaskId_ = task->taskId_;
694     groupManager.TriggerSeqRunner(env, task);
695     seqRunner->seqRunnerRef_ = CreateReference(env);
696     task1->taskState_ = ExecuteState::CANCELED;
697     seqRunner->seqRunnerTasks_.push(task1);
698     TaskInfo* taskInfo = new TaskInfo();
699     task1->currentTaskInfo_ = taskInfo;
700     seqRunner->currentTaskId_ = task->taskId_;
701     groupManager.TriggerSeqRunner(env, task);
702     seqRunner->seqRunnerRef_ = CreateReference(env);
703     TaskInfo* taskInfo1 = new TaskInfo();
704     task1->currentTaskInfo_ = taskInfo1;
705     seqRunner->seqRunnerTasks_.push(task1);
706     seqRunner->seqRunnerTasks_.push(task);
707     task->taskState_ = ExecuteState::RUNNING;
708     seqRunner->currentTaskId_ = task->taskId_;
709     groupManager.TriggerSeqRunner(env, task);
710 }
711 
UpdateGroupState(napi_env env)712 void NativeEngineTest::UpdateGroupState(napi_env env)
713 {
714     TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
715     TaskGroup* group = new TaskGroup();
716     uint64_t groupId = reinterpret_cast<uint64_t>(group);
717     Task* task = new Task();
718     task->taskId_ = reinterpret_cast<uint64_t>(task);
719     groupManager.StoreTaskGroup(groupId, group);
720     groupManager.UpdateGroupState(task->taskId_);
721     group->groupState_ = ExecuteState::CANCELED;
722     groupManager.UpdateGroupState(groupId);
723     group->groupState_ = ExecuteState::WAITING;
724     groupManager.UpdateGroupState(groupId);
725 
726     SequenceRunnerManager& runnerManager = SequenceRunnerManager::GetInstance();
727     napi_value obj = NapiHelper::CreateObject(env);
728     SequenceRunner* seqRunner = runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_THREE_, "test", UINT32_ONE_);
729     seqRunner->priority_ = Priority::MEDIUM;
730     runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_TWO_, "test", UINT32_ZERO_);
731     runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_TWO_, "test", UINT32_ONE_);
732     runnerManager.DecreaseSeqCount(seqRunner);
733     runnerManager.RemoveGlobalSeqRunnerRef(env, seqRunner);
734     runnerManager.RemoveSequenceRunner("func");
735     runnerManager.RemoveSequenceRunner("test");
736 }
737 
ReleaseWorkerHandles(napi_env env)738 void NativeEngineTest::ReleaseWorkerHandles(napi_env env)
739 {
740     ExceptionScope scope(env);
741     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
742     napi_env workerEnv = nullptr;
743     napi_create_runtime(env, &workerEnv);
744     worker->workerEnv_ = workerEnv;
745     NativeEngine* workerEngine = reinterpret_cast<NativeEngine*>(workerEnv);
746     uv_loop_t* loop = worker->GetWorkerLoop();
747     ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_,
748                                    NativeEngineTest::foo, worker);
749     ConcurrentHelper::UvHandleInit(loop, worker->debuggerOnPostTaskSignal_,
750                                    NativeEngineTest::foo, worker);
751     ConcurrentHelper::UvHandleInit(loop, worker->clearWorkerSignal_,
752                                    NativeEngineTest::foo, worker);
753     uv_async_t* req = new uv_async_t;
754     req->data = worker;
755     Worker::ReleaseWorkerHandles(req);
756 }
757 
DebuggerOnPostTask(napi_env env)758 void NativeEngineTest::DebuggerOnPostTask(napi_env env)
759 {
760     ExceptionScope scope(env);
761     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
762     uv_loop_t* loop = worker->GetWorkerLoop();
763     ConcurrentHelper::UvHandleInit(loop, worker->debuggerOnPostTaskSignal_,
764                                    NativeEngineTest::foo, worker);
765     std::function<void()> myTask = []() {
766         return;
767     };
768     worker->DebuggerOnPostTask(std::move(myTask));
769     uv_async_t* req = new uv_async_t;
770     std::function<void()> myTask1 = []() {
771         return;
772     };
773     worker->debuggerQueue_.push(myTask1);
774     req->data = worker;
775     worker->debuggerMutex_.unlock();
776     Worker::HandleDebuggerTask(req);
777     worker->workerEnv_ = nullptr;
778     worker->ReleaseWorkerThreadContent();
779     napi_env workerEnv = nullptr;
780     napi_create_runtime(env, &workerEnv);
781     worker->workerEnv_ = workerEnv;
782     worker->hostEnv_ = nullptr;
783     worker->state_ = WorkerState::BLOCKED;
784     worker->ReleaseWorkerThreadContent();
785     napi_env workerEnv1 = nullptr;
786     napi_create_runtime(env, &workerEnv1);
787     worker->hostEnv_ = env;
788     worker->workerEnv_ = workerEnv1;
789     worker->state_ = WorkerState::IDLE;
790     worker->ReleaseWorkerThreadContent();
791 }
792 
PerformTask(napi_env env)793 void NativeEngineTest::PerformTask(napi_env env)
794 {
795     ExceptionScope scope(env);
796     TaskManager& taskManager = TaskManager::GetInstance();
797     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
798     napi_env workerEnv = nullptr;
799     napi_create_runtime(env, &workerEnv);
800     worker->workerEnv_ = workerEnv;
801 
802     TaskGroup* group = new TaskGroup();
803     uint64_t groupId = reinterpret_cast<uint64_t>(group);
804     group->groupState_ = ExecuteState::WAITING;
805     TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
806     groupManager.StoreTaskGroup(groupId, group);
807 
808     Task* task = new Task();
809     task->taskId_ = reinterpret_cast<uint64_t>(task);
810     taskManager.StoreTask(task->taskId_, task);
811     Priority priority = Priority::DEFAULT;
812     auto& mediumTaskQueue = taskManager.taskQueues_[priority];
813     uint64_t id = mediumTaskQueue->DequeueTaskId();
814     while (id != 0) {
815         id = mediumTaskQueue->DequeueTaskId();
816     }
817     mediumTaskQueue->EnqueueTaskId(task->taskId_);
818 
819     uv_async_t* req = new uv_async_t;
820     req->data = worker;
821     task->taskState_ = ExecuteState::WAITING;
822     task->taskType_ = TaskType::GROUP_COMMON_TASK;
823     task->groupId_ = groupId;
824     Worker::PerformTask(req);
825     usleep(100000); // 100000: is sleep 100ms
826 }
827 
NotifyHandleTaskResult(napi_env env)828 void NativeEngineTest::NotifyHandleTaskResult(napi_env env)
829 {
830     ExceptionScope scope(env);
831     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
832     Task* task = new Task();
833     task->taskId_ = reinterpret_cast<uint64_t>(task);
834     task->env_ = worker->workerEnv_;
835     uv_loop_t* loop = worker->GetWorkerLoop();
836     ConcurrentHelper::UvHandleInit(loop, task->onResultSignal_, NativeEngineTest::foo, task);
837     Task* task1 = new Task();
838     task1->taskId_ = reinterpret_cast<uint64_t>(task1);
839     worker->currentTaskId_.push_back(task1->taskId_);
840     task->worker_ = worker;
841     task->isMainThreadTask_ = true;
842     task->taskRefCount_.fetch_add(1);
843     TaskManager::GetInstance().StoreTask(task->taskId_, task);
844     Worker::NotifyHandleTaskResult(task);
845 }
846 
TaskResultCallback(napi_env env)847 void NativeEngineTest::TaskResultCallback(napi_env env)
848 {
849     ExceptionScope scope(env);
850     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
851     Task* task = new Task();
852     task->taskId_ = reinterpret_cast<uint64_t>(task);
853     task->env_ = worker->workerEnv_;
854     task->taskRefCount_.fetch_add(1);
855     task->worker_ = worker;
856     task->cpuTime_ = UINT64_ZERO_;
857     Worker::TaskResultCallback(worker->workerEnv_, nullptr, false, reinterpret_cast<void*>(task));
858     task->taskRefCount_.fetch_add(1);
859     task->cpuTime_ = task->taskId_;
860     Worker::TaskResultCallback(worker->workerEnv_, nullptr, true, reinterpret_cast<void*>(task));
861 
862     worker->priority_ = Priority::LOW;
863     worker->ResetWorkerPriority();
864     TaskManager& taskManager = TaskManager::GetInstance();
865     taskManager.globalEnableFfrtFlag_ = true;
866     worker->priority_ = Priority::HIGH;
867     worker->ResetWorkerPriority();
868     taskManager.globalEnableFfrtFlag_ = false;
869     worker->state_ = WorkerState::BLOCKED;
870     worker->UpdateExecutedInfo();
871     worker->state_ = WorkerState::IDLE;
872     worker->UpdateExecutedInfo();
873 
874     uint64_t id = task->taskId_ + MAX_TIMEOUT_TIME;
875     std::unordered_set<uint64_t> set{ task->taskId_, id };
876     worker->longTasksSet_ = std::move(set);
877     worker->TerminateTask(task->taskId_);
878 }
879 
HandleFunctionException(napi_env env)880 void NativeEngineTest::HandleFunctionException(napi_env env)
881 {
882     ExceptionScope scope(env);
883     Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
884     napi_env workerEnv = nullptr;
885     napi_create_runtime(env, &workerEnv);
886     worker->workerEnv_ = workerEnv;
887     Task* task = new Task();
888     task->taskId_ = reinterpret_cast<uint64_t>(task);
889     task->env_ = workerEnv;
890     TaskResultInfo* resultInfo = new TaskResultInfo(env, workerEnv, task->taskId_, nullptr);
891     TaskManager::GetInstance().NotifyCallbackExecute(env, resultInfo, task);
892     task->IncreaseRefCount();
893     uv_loop_t* loop = NapiHelper::GetLibUV(env);
894     ConcurrentHelper::UvHandleInit(loop, task->onResultSignal_, NativeEngineTest::foo, task);
895     task->worker_ = worker;
896     Worker::HandleFunctionException(env, task);
897     task->IncreaseRefCount();
898     Worker::HandleFunctionException(env, task);
899 }
900 
WorkerConstructor(napi_env env)901 void* NativeEngineTest::WorkerConstructor(napi_env env)
902 {
903     uint32_t sleepTime = 50000; // 50000: is sleep 50ms
904     Worker* worker = Worker::WorkerConstructor(env);
905     usleep(sleepTime);
906     uv_loop_t* loop = worker->GetWorkerLoop();
907     ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_, NativeEngineTest::foo, worker);
908     return worker;
909 }
910 
GetWorkerTid(uv_timer_t * handle)911 pid_t NativeEngineTest::GetWorkerTid(uv_timer_t* handle)
912 {
913     Worker* worker = reinterpret_cast<Worker*>(handle->data);
914     return worker->tid_;
915 }
916 } // namespace Commonlibrary::Concurrent::TaskPoolModule