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
29namespace Commonlibrary::Concurrent::TaskPoolModule {
30
31static constexpr uint32_t MAX_TIMEOUT_TIME = 600000;
32static constexpr uint32_t FINSHED_TASK_ = 5;
33static constexpr uint32_t TASK_NUMS_ = 7;
34static constexpr uint64_t UINT64_ZERO_ = 0;
35static constexpr uint32_t UINT32_ZERO_ = 0;
36static constexpr uint32_t UINT32_ONE_ = 1;
37static constexpr size_t SIZE_TWO_ = 2;
38static constexpr size_t SIZE_THREE_ = 3;
39
40napi_ref CreateReference(napi_env env)
41{
42    napi_value obj = NapiHelper::CreateObject(env);
43    return NapiHelper::CreateReference(env, obj, 1);
44}
45
46napi_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
65napi_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
73napi_value SendableUtils::Foo(napi_env env, napi_callback_info info)
74{
75    return nullptr;
76}
77
78napi_value SendableUtils::Bar(napi_env env, napi_callback_info info)
79{
80    return nullptr;
81}
82
83napi_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
93napi_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
103napi_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
113napi_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
123napi_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
133napi_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
143void NativeEngineTest::TaskGroupDestructor(napi_env env, void* data)
144{
145    void* hint = nullptr;
146    TaskGroup::TaskGroupDestructor(env, data, hint);
147}
148
149void NativeEngineTest::SequenceRunnerDestructor(napi_env env, void* data)
150{
151    void* hint = nullptr;
152    SequenceRunner::SequenceRunnerDestructor(env, data, hint);
153}
154
155napi_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
165napi_value NativeEngineTest::ExecuteGroup(napi_env env, napi_value taskGroup)
166{
167    return TaskPool::ExecuteGroup(env, taskGroup, Priority::DEFAULT);
168}
169
170void NativeEngineTest::DelayTask(uv_timer_t* handle)
171{
172    TaskPool::DelayTask(handle);
173}
174
175void NativeEngineTest::PeriodicTaskCallback(uv_timer_t* handle)
176{
177    TaskPool::PeriodicTaskCallback(handle);
178}
179
180void 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
186void 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
195void 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
225void NativeEngineTest::foo(const uv_async_t* req)
226{
227    return;
228}
229
230void 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
264void 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
305void 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
326void 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
361void 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
378void 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
399void 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
419void 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
437void 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
444void 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
451void 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
459void 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
473void 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
497void 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
535void 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
562void 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
597void 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->finishedTask = 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
647void NativeEngineTest::CancelGroupTask(napi_env env)
648{
649    TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
650    TaskManager& taskManager = TaskManager::GetInstance();
651    TaskGroup* group = new TaskGroup();
652    Task* task = new Task();
653    task->taskId_ = reinterpret_cast<uint64_t>(task);
654    taskManager.StoreTask(task->taskId_, task);
655    task->taskState_ = ExecuteState::RUNNING;
656    groupManager.CancelGroupTask(env, task->taskId_, group);
657    task->taskState_ = ExecuteState::WAITING;
658    groupManager.CancelGroupTask(env, task->taskId_, group);
659    task->taskState_ = ExecuteState::WAITING;
660    TaskInfo* taskInfo = new TaskInfo();
661    task->currentTaskInfo_ = taskInfo;
662    groupManager.CancelGroupTask(env, task->taskId_, group);
663
664    Task* task1 = new Task();
665    task1->taskId_ = reinterpret_cast<uint64_t>(task1);
666    SequenceRunner* seqRunner = new SequenceRunner();
667    uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
668    groupManager.StoreSequenceRunner(seqRunnerId, seqRunner);
669    groupManager.AddTaskToSeqRunner(seqRunnerId, task1);
670}
671
672void NativeEngineTest::TriggerSeqRunner(napi_env env)
673{
674    TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
675    Task* task = new Task();
676    task->taskId_ = reinterpret_cast<uint64_t>(task);
677    Task* task1 = new Task();
678    task1->taskId_ = reinterpret_cast<uint64_t>(task1);
679    SequenceRunner* seqRunner = new SequenceRunner();
680    uint64_t seqRunnerId = reinterpret_cast<uint64_t>(seqRunner);
681    seqRunner->priority_ = Priority::DEFAULT;
682    task->seqRunnerId_ = seqRunnerId;
683    groupManager.StoreSequenceRunner(seqRunnerId, seqRunner);
684    seqRunner->isGlobalRunner_ = true;
685    bool res = groupManager.TriggerSeqRunner(env, task);
686    ASSERT_FALSE(res);
687    seqRunner->globalSeqRunnerRef_.emplace(env, CreateReference(env));
688    seqRunner->currentTaskId_ = task1->taskId_;
689    groupManager.TriggerSeqRunner(env, task);
690    seqRunner->isGlobalRunner_ = false;
691    seqRunner->seqRunnerRef_ = CreateReference(env);
692    seqRunner->currentTaskId_ = task->taskId_;
693    groupManager.TriggerSeqRunner(env, task);
694    seqRunner->seqRunnerRef_ = CreateReference(env);
695    task1->taskState_ = ExecuteState::CANCELED;
696    seqRunner->seqRunnerTasks_.push(task1);
697    TaskInfo* taskInfo = new TaskInfo();
698    task1->currentTaskInfo_ = taskInfo;
699    seqRunner->currentTaskId_ = task->taskId_;
700    groupManager.TriggerSeqRunner(env, task);
701    seqRunner->seqRunnerRef_ = CreateReference(env);
702    TaskInfo* taskInfo1 = new TaskInfo();
703    task1->currentTaskInfo_ = taskInfo1;
704    seqRunner->seqRunnerTasks_.push(task1);
705    seqRunner->seqRunnerTasks_.push(task);
706    task->taskState_ = ExecuteState::RUNNING;
707    seqRunner->currentTaskId_ = task->taskId_;
708    groupManager.TriggerSeqRunner(env, task);
709}
710
711void NativeEngineTest::UpdateGroupState(napi_env env)
712{
713    TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
714    TaskGroup* group = new TaskGroup();
715    uint64_t groupId = reinterpret_cast<uint64_t>(group);
716    Task* task = new Task();
717    task->taskId_ = reinterpret_cast<uint64_t>(task);
718    groupManager.StoreTaskGroup(groupId, group);
719    groupManager.UpdateGroupState(task->taskId_);
720    group->groupState_ = ExecuteState::CANCELED;
721    groupManager.UpdateGroupState(groupId);
722    group->groupState_ = ExecuteState::WAITING;
723    groupManager.UpdateGroupState(groupId);
724
725    SequenceRunnerManager& runnerManager = SequenceRunnerManager::GetInstance();
726    napi_value obj = NapiHelper::CreateObject(env);
727    SequenceRunner* seqRunner = runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_THREE_, "test", UINT32_ONE_);
728    seqRunner->priority_ = Priority::MEDIUM;
729    runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_TWO_, "test", UINT32_ZERO_);
730    runnerManager.CreateOrGetGlobalRunner(env, obj, SIZE_TWO_, "test", UINT32_ONE_);
731    runnerManager.DecreaseSeqCount(seqRunner);
732    runnerManager.RemoveGlobalSeqRunnerRef(env, seqRunner);
733    runnerManager.RemoveSequenceRunner("func");
734    runnerManager.RemoveSequenceRunner("test");
735}
736
737void NativeEngineTest::ReleaseWorkerHandles(napi_env env)
738{
739    ExceptionScope scope(env);
740    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
741    napi_env workerEnv = nullptr;
742    napi_create_runtime(env, &workerEnv);
743    worker->workerEnv_ = workerEnv;
744    NativeEngine* workerEngine = reinterpret_cast<NativeEngine*>(workerEnv);
745    uv_loop_t* loop = worker->GetWorkerLoop();
746    ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_,
747                                   NativeEngineTest::foo, worker);
748    ConcurrentHelper::UvHandleInit(loop, worker->debuggerOnPostTaskSignal_,
749                                   NativeEngineTest::foo, worker);
750    ConcurrentHelper::UvHandleInit(loop, worker->clearWorkerSignal_,
751                                   NativeEngineTest::foo, worker);
752    uv_async_t* req = new uv_async_t;
753    req->data = worker;
754    Worker::ReleaseWorkerHandles(req);
755}
756
757void NativeEngineTest::DebuggerOnPostTask(napi_env env)
758{
759    ExceptionScope scope(env);
760    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
761    uv_loop_t* loop = worker->GetWorkerLoop();
762    ConcurrentHelper::UvHandleInit(loop, worker->debuggerOnPostTaskSignal_,
763                                   NativeEngineTest::foo, worker);
764    std::function<void()> myTask = []() {
765        return;
766    };
767    worker->DebuggerOnPostTask(std::move(myTask));
768    uv_async_t* req = new uv_async_t;
769    std::function<void()> myTask1 = []() {
770        return;
771    };
772    worker->debuggerQueue_.push(myTask1);
773    req->data = worker;
774    worker->debuggerMutex_.unlock();
775    Worker::HandleDebuggerTask(req);
776    worker->workerEnv_ = nullptr;
777    worker->ReleaseWorkerThreadContent();
778    napi_env workerEnv = nullptr;
779    napi_create_runtime(env, &workerEnv);
780    worker->workerEnv_ = workerEnv;
781    worker->hostEnv_ = nullptr;
782    worker->state_ = WorkerState::BLOCKED;
783    worker->ReleaseWorkerThreadContent();
784    napi_env workerEnv1 = nullptr;
785    napi_create_runtime(env, &workerEnv1);
786    worker->hostEnv_ = env;
787    worker->workerEnv_ = workerEnv1;
788    worker->state_ = WorkerState::IDLE;
789    worker->ReleaseWorkerThreadContent();
790}
791
792void NativeEngineTest::PerformTask(napi_env env)
793{
794    ExceptionScope scope(env);
795    TaskManager& taskManager = TaskManager::GetInstance();
796    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
797    napi_env workerEnv = nullptr;
798    napi_create_runtime(env, &workerEnv);
799    worker->workerEnv_ = workerEnv;
800
801    TaskGroup* group = new TaskGroup();
802    uint64_t groupId = reinterpret_cast<uint64_t>(group);
803    group->groupState_ = ExecuteState::WAITING;
804    TaskGroupManager& groupManager = TaskGroupManager::GetInstance();
805    groupManager.StoreTaskGroup(groupId, group);
806
807    Task* task = new Task();
808    task->taskId_ = reinterpret_cast<uint64_t>(task);
809    taskManager.StoreTask(task->taskId_, task);
810    Priority priority = Priority::DEFAULT;
811    auto& mediumTaskQueue = taskManager.taskQueues_[priority];
812    uint64_t id = mediumTaskQueue->DequeueTaskId();
813    while (id != 0) {
814        id = mediumTaskQueue->DequeueTaskId();
815    }
816    mediumTaskQueue->EnqueueTaskId(task->taskId_);
817
818    uv_async_t* req = new uv_async_t;
819    req->data = worker;
820    task->taskState_ = ExecuteState::WAITING;
821    task->taskType_ = TaskType::GROUP_COMMON_TASK;
822    task->groupId_ = groupId;
823    Worker::PerformTask(req);
824    usleep(100000); // 100000: is sleep 100ms
825}
826
827void NativeEngineTest::NotifyHandleTaskResult(napi_env env)
828{
829    ExceptionScope scope(env);
830    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
831    Task* task = new Task();
832    task->taskId_ = reinterpret_cast<uint64_t>(task);
833    task->env_ = worker->workerEnv_;
834    uv_loop_t* loop = worker->GetWorkerLoop();
835    ConcurrentHelper::UvHandleInit(loop, task->onResultSignal_, NativeEngineTest::foo, task);
836    Task* task1 = new Task();
837    task1->taskId_ = reinterpret_cast<uint64_t>(task1);
838    worker->currentTaskId_.push_back(task1->taskId_);
839    task->worker_ = worker;
840    task->isMainThreadTask_ = true;
841    task->taskRefCount_.fetch_add(1);
842    TaskManager::GetInstance().StoreTask(task->taskId_, task);
843    Worker::NotifyHandleTaskResult(task);
844}
845
846void NativeEngineTest::TaskResultCallback(napi_env env)
847{
848    ExceptionScope scope(env);
849    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
850    Task* task = new Task();
851    task->taskId_ = reinterpret_cast<uint64_t>(task);
852    task->env_ = worker->workerEnv_;
853    task->taskRefCount_.fetch_add(1);
854    task->worker_ = worker;
855    task->cpuTime_ = UINT64_ZERO_;
856    Worker::TaskResultCallback(worker->workerEnv_, nullptr, false, reinterpret_cast<void*>(task));
857    task->taskRefCount_.fetch_add(1);
858    task->cpuTime_ = task->taskId_;
859    Worker::TaskResultCallback(worker->workerEnv_, nullptr, true, reinterpret_cast<void*>(task));
860
861    worker->priority_ = Priority::LOW;
862    worker->ResetWorkerPriority();
863    TaskManager& taskManager = TaskManager::GetInstance();
864    taskManager.globalEnableFfrtFlag_ = true;
865    worker->priority_ = Priority::HIGH;
866    worker->ResetWorkerPriority();
867    taskManager.globalEnableFfrtFlag_ = false;
868    worker->state_ = WorkerState::BLOCKED;
869    worker->UpdateExecutedInfo();
870    worker->state_ = WorkerState::IDLE;
871    worker->UpdateExecutedInfo();
872
873    uint64_t id = task->taskId_ + MAX_TIMEOUT_TIME;
874    std::unordered_set<uint64_t> set{ task->taskId_, id };
875    worker->longTasksSet_ = std::move(set);
876    worker->TerminateTask(task->taskId_);
877}
878
879void NativeEngineTest::HandleFunctionException(napi_env env)
880{
881    ExceptionScope scope(env);
882    Worker* worker = reinterpret_cast<Worker*>(WorkerConstructor(env));
883    napi_env workerEnv = nullptr;
884    napi_create_runtime(env, &workerEnv);
885    worker->workerEnv_ = workerEnv;
886    Task* task = new Task();
887    task->taskId_ = reinterpret_cast<uint64_t>(task);
888    task->env_ = workerEnv;
889    TaskResultInfo* resultInfo = new TaskResultInfo(env, workerEnv, task->taskId_, nullptr);
890    TaskManager::GetInstance().NotifyCallbackExecute(env, resultInfo, task);
891    task->IncreaseRefCount();
892    uv_loop_t* loop = NapiHelper::GetLibUV(env);
893    ConcurrentHelper::UvHandleInit(loop, task->onResultSignal_, NativeEngineTest::foo, task);
894    task->worker_ = worker;
895    Worker::HandleFunctionException(env, task);
896    task->IncreaseRefCount();
897    Worker::HandleFunctionException(env, task);
898}
899
900void* NativeEngineTest::WorkerConstructor(napi_env env)
901{
902    uint32_t sleepTime = 50000; // 50000: is sleep 50ms
903    Worker* worker = Worker::WorkerConstructor(env);
904    usleep(sleepTime);
905    uv_loop_t* loop = worker->GetWorkerLoop();
906    ConcurrentHelper::UvHandleInit(loop, worker->performTaskSignal_, NativeEngineTest::foo, worker);
907    return worker;
908}
909
910pid_t NativeEngineTest::GetWorkerTid(uv_timer_t* handle)
911{
912    Worker* worker = reinterpret_cast<Worker*>(handle->data);
913    return worker->tid_;
914}
915} // namespace Commonlibrary::Concurrent::TaskPoolModule