1484543d1Sopenharmony_ci/*
2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License.
5484543d1Sopenharmony_ci * You may obtain a copy of the License at
6484543d1Sopenharmony_ci *
7484543d1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8484543d1Sopenharmony_ci *
9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and
13484543d1Sopenharmony_ci * limitations under the License.
14484543d1Sopenharmony_ci */
15484543d1Sopenharmony_ci
16484543d1Sopenharmony_ci#include <list>
17484543d1Sopenharmony_ci#include <vector>
18484543d1Sopenharmony_ci#include <queue>
19484543d1Sopenharmony_ci#include <thread>
20484543d1Sopenharmony_ci#include <gtest/gtest.h>
21484543d1Sopenharmony_ci#define private public
22484543d1Sopenharmony_ci#define protect public
23484543d1Sopenharmony_ci#include "ffrt_inner.h"
24484543d1Sopenharmony_ci
25484543d1Sopenharmony_ci#include "core/entity.h"
26484543d1Sopenharmony_ci#include "sched/task_scheduler.h"
27484543d1Sopenharmony_ci#include "sched/task_manager.h"
28484543d1Sopenharmony_ci#include "core/task_attr_private.h"
29484543d1Sopenharmony_ci#include "tm/scpu_task.h"
30484543d1Sopenharmony_ci#include "sched/scheduler.h"
31484543d1Sopenharmony_ci#include "../common.h"
32484543d1Sopenharmony_ci
33484543d1Sopenharmony_ciusing namespace std;
34484543d1Sopenharmony_ciusing namespace testing;
35484543d1Sopenharmony_ci#ifdef HWTEST_TESTING_EXT_ENABLE
36484543d1Sopenharmony_ciusing namespace testing::ext;
37484543d1Sopenharmony_ci#endif
38484543d1Sopenharmony_ciusing namespace ffrt;
39484543d1Sopenharmony_ci
40484543d1Sopenharmony_ciclass SchedulerTest : public testing::Test {
41484543d1Sopenharmony_ciprotected:
42484543d1Sopenharmony_ci    static void SetUpTestCase()
43484543d1Sopenharmony_ci    {
44484543d1Sopenharmony_ci    }
45484543d1Sopenharmony_ci
46484543d1Sopenharmony_ci    static void TearDownTestCase()
47484543d1Sopenharmony_ci    {
48484543d1Sopenharmony_ci    }
49484543d1Sopenharmony_ci
50484543d1Sopenharmony_ci    virtual void SetUp()
51484543d1Sopenharmony_ci    {
52484543d1Sopenharmony_ci    }
53484543d1Sopenharmony_ci
54484543d1Sopenharmony_ci    virtual void TearDown()
55484543d1Sopenharmony_ci    {
56484543d1Sopenharmony_ci    }
57484543d1Sopenharmony_ci};
58484543d1Sopenharmony_ci
59484543d1Sopenharmony_ciHWTEST_F(SchedulerTest, taskstate_test, TestSize.Level1)
60484543d1Sopenharmony_ci{
61484543d1Sopenharmony_ci    std::queue<std::unique_ptr<SCPUEUTask>> tasks;
62484543d1Sopenharmony_ci
63484543d1Sopenharmony_ci    std::vector<TaskState::State> produceStatus;
64484543d1Sopenharmony_ci    std::vector<TaskState::State> consumeStatus;
65484543d1Sopenharmony_ci
66484543d1Sopenharmony_ci#if (TASKSTAT_LOG_ENABLE == 1)
67484543d1Sopenharmony_ci    std::array<uint64_t, static_cast<size_t>(TaskState::MAX)> expectCount;
68484543d1Sopenharmony_ci
69484543d1Sopenharmony_ci    // record previous test units count
70484543d1Sopenharmony_ci    for (auto state = TaskState::PENDING; state != TaskState::MAX; ++(size_t&)state) {
71484543d1Sopenharmony_ci        expectCount[static_cast<size_t>(state)] = TaskManager::Instance().GetCount(state);
72484543d1Sopenharmony_ci    }
73484543d1Sopenharmony_ci
74484543d1Sopenharmony_ci    // expect non-exited state count equal zero
75484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::PENDING)], 0);
76484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], 0);
77484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::RUNNING)], 0);
78484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::BLOCKED)], 0);
79484543d1Sopenharmony_ci
80484543d1Sopenharmony_ci    auto increCount = [&expectCount](TaskState::State state) { ++expectCount[static_cast<size_t>(state)]; };
81484543d1Sopenharmony_ci
82484543d1Sopenharmony_ci    auto decreCount = [&expectCount](TaskState::State state) {
83484543d1Sopenharmony_ci        if (expectCount[static_cast<size_t>(state)] > 0) {
84484543d1Sopenharmony_ci            --expectCount[static_cast<size_t>(state)];
85484543d1Sopenharmony_ci        }
86484543d1Sopenharmony_ci    };
87484543d1Sopenharmony_ci#endif
88484543d1Sopenharmony_ci    auto setState = [&](CPUEUTask* task) {
89484543d1Sopenharmony_ci        consumeStatus.emplace_back(task->state());
90484543d1Sopenharmony_ci        return true;
91484543d1Sopenharmony_ci    };
92484543d1Sopenharmony_ci
93484543d1Sopenharmony_ci    auto getNextState = [](TaskState::State state) {
94484543d1Sopenharmony_ci        switch (state) {
95484543d1Sopenharmony_ci            case TaskState::PENDING:
96484543d1Sopenharmony_ci                return TaskState::READY;
97484543d1Sopenharmony_ci            case TaskState::READY:
98484543d1Sopenharmony_ci                return TaskState::RUNNING;
99484543d1Sopenharmony_ci            case TaskState::RUNNING:
100484543d1Sopenharmony_ci                return TaskState::BLOCKED;
101484543d1Sopenharmony_ci            case TaskState::BLOCKED:
102484543d1Sopenharmony_ci                return TaskState::EXITED;
103484543d1Sopenharmony_ci            default:
104484543d1Sopenharmony_ci                break;
105484543d1Sopenharmony_ci        }
106484543d1Sopenharmony_ci        return TaskState::MAX;
107484543d1Sopenharmony_ci    };
108484543d1Sopenharmony_ci
109484543d1Sopenharmony_ci    TaskState::RegisterOps(TaskState::READY, setState);
110484543d1Sopenharmony_ci    TaskState::RegisterOps(TaskState::RUNNING, setState);
111484543d1Sopenharmony_ci    TaskState::RegisterOps(TaskState::BLOCKED, setState);
112484543d1Sopenharmony_ci    TaskState::RegisterOps(TaskState::EXITED, setState);
113484543d1Sopenharmony_ci
114484543d1Sopenharmony_ci    task_attr_private task_attr;
115484543d1Sopenharmony_ci    task_attr.name_ = "root";
116484543d1Sopenharmony_ci    auto root = std::make_unique<SCPUEUTask>(
117484543d1Sopenharmony_ci        &task_attr, nullptr, 0);
118484543d1Sopenharmony_ci    for (int i = 1; i <= 1000; ++i) {
119484543d1Sopenharmony_ci        task_attr_private task_attr;
120484543d1Sopenharmony_ci        task_attr.name_ = "i";
121484543d1Sopenharmony_ci        tasks.push(std::make_unique<SCPUEUTask>(
122484543d1Sopenharmony_ci            &task_attr, root.get(), i));
123484543d1Sopenharmony_ci    }
124484543d1Sopenharmony_ci
125484543d1Sopenharmony_ci    while (!tasks.empty()) {
126484543d1Sopenharmony_ci        auto task = std::move(tasks.front());
127484543d1Sopenharmony_ci        tasks.pop();
128484543d1Sopenharmony_ci
129484543d1Sopenharmony_ci        auto state = getNextState(task->state());
130484543d1Sopenharmony_ci        if (state == TaskState::MAX) {
131484543d1Sopenharmony_ci            continue;
132484543d1Sopenharmony_ci        }
133484543d1Sopenharmony_ci
134484543d1Sopenharmony_ci        produceStatus.emplace_back(state);
135484543d1Sopenharmony_ci
136484543d1Sopenharmony_ci        task->UpdateState(state);
137484543d1Sopenharmony_ci
138484543d1Sopenharmony_ci#if (TASKSTAT_LOG_ENABLE == 1)
139484543d1Sopenharmony_ci        auto preState = task->state.PreState();
140484543d1Sopenharmony_ci        auto curState = task->state.CurState();
141484543d1Sopenharmony_ci
142484543d1Sopenharmony_ci        decreCount(preState);
143484543d1Sopenharmony_ci        increCount(curState);
144484543d1Sopenharmony_ci
145484543d1Sopenharmony_ci        EXPECT_EQ(expectCount[static_cast<size_t>(preState)], TaskManager::Instance().GetCount(preState));
146484543d1Sopenharmony_ci        EXPECT_EQ(expectCount[static_cast<size_t>(curState)], TaskManager::Instance().GetCount(curState));
147484543d1Sopenharmony_ci#endif
148484543d1Sopenharmony_ci
149484543d1Sopenharmony_ci        tasks.push(std::move(task));
150484543d1Sopenharmony_ci    }
151484543d1Sopenharmony_ci
152484543d1Sopenharmony_ci#if (TRACE_TASKSTAT_LOG_ENABLE == 1)
153484543d1Sopenharmony_ci    EXPECT_EQ(
154484543d1Sopenharmony_ci        expectCount[static_cast<size_t>(TaskState::PENDING)], TaskManager::Instance().GetCount(TaskState::PENDING));
155484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], TaskManager::Instance().GetCount(TaskState::READY));
156484543d1Sopenharmony_ci    EXPECT_EQ(
157484543d1Sopenharmony_ci        expectCount[static_cast<size_t>(TaskState::RUNNING)], TaskManager::Instance().GetCount(TaskState::RUNNING));
158484543d1Sopenharmony_ci    EXPECT_EQ(
159484543d1Sopenharmony_ci        expectCount[static_cast<size_t>(TaskState::BLOCKED)], TaskManager::Instance().GetCount(TaskState::BLOCKED));
160484543d1Sopenharmony_ci    EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::EXITED)], TaskManager::Instance().GetCount(TaskState::EXITED));
161484543d1Sopenharmony_ci#endif
162484543d1Sopenharmony_ci
163484543d1Sopenharmony_ci    EXPECT_EQ(produceStatus.size(), consumeStatus.size());
164484543d1Sopenharmony_ci
165484543d1Sopenharmony_ci    int size = produceStatus.size();
166484543d1Sopenharmony_ci    for (int i = 0; i < size; ++i) {
167484543d1Sopenharmony_ci        EXPECT_EQ(produceStatus[i], consumeStatus[i]);
168484543d1Sopenharmony_ci    }
169484543d1Sopenharmony_ci}
170484543d1Sopenharmony_ci
171484543d1Sopenharmony_ciHWTEST_F(SchedulerTest, taskstateCount_test, TestSize.Level1)
172484543d1Sopenharmony_ci{
173484543d1Sopenharmony_ci    SCPUEUTask* task1 = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
174484543d1Sopenharmony_ci    SCPUEUTask *task2 = new SCPUEUTask(nullptr, task1, 0, QoS());
175484543d1Sopenharmony_ci    TaskManager::Instance().TaskStateCount(task2);
176484543d1Sopenharmony_ci}
177484543d1Sopenharmony_ci
178484543d1Sopenharmony_ciHWTEST_F(SchedulerTest, ffrt_task_runqueue_test, TestSize.Level1)
179484543d1Sopenharmony_ci{
180484543d1Sopenharmony_ci    ffrt::FIFOQueue *fifoqueue = new ffrt::FIFOQueue();
181484543d1Sopenharmony_ci    int aimnum = 10;
182484543d1Sopenharmony_ci    for (int i = 0; i < aimnum ; i++) {
183484543d1Sopenharmony_ci        SCPUEUTask* task = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
184484543d1Sopenharmony_ci        fifoqueue->EnQueue(task);
185484543d1Sopenharmony_ci    }
186484543d1Sopenharmony_ci    EXPECT_EQ(fifoqueue->Size(), aimnum);
187484543d1Sopenharmony_ci    EXPECT_EQ(fifoqueue->Empty(), false);
188484543d1Sopenharmony_ci}
189484543d1Sopenharmony_ci
190484543d1Sopenharmony_ciHWTEST_F(SchedulerTest, ffrt_scheduler_test, TestSize.Level1)
191484543d1Sopenharmony_ci{
192484543d1Sopenharmony_ci    ffrt::SFFRTScheduler *sffrtscheduler = new ffrt::SFFRTScheduler();
193484543d1Sopenharmony_ci    LinkedList* node = new LinkedList();
194484543d1Sopenharmony_ci    QoS qos;
195484543d1Sopenharmony_ci    EXPECT_EQ(sffrtscheduler->InsertNode(node, qos), true);
196484543d1Sopenharmony_ci    EXPECT_EQ(sffrtscheduler->RemoveNode(node, qos), true);
197484543d1Sopenharmony_ci
198484543d1Sopenharmony_ci    delete node;
199484543d1Sopenharmony_ci}
200