1 /*
2  * Copyright (c) 2023 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 <list>
17 #include <vector>
18 #include <queue>
19 #include <thread>
20 #include <gtest/gtest.h>
21 #define private public
22 #define protect public
23 #include "ffrt_inner.h"
24 
25 #include "core/entity.h"
26 #include "sched/task_scheduler.h"
27 #include "sched/task_manager.h"
28 #include "core/task_attr_private.h"
29 #include "tm/scpu_task.h"
30 #include "sched/scheduler.h"
31 #include "../common.h"
32 
33 using namespace std;
34 using namespace testing;
35 #ifdef HWTEST_TESTING_EXT_ENABLE
36 using namespace testing::ext;
37 #endif
38 using namespace ffrt;
39 
40 class SchedulerTest : public testing::Test {
41 protected:
SetUpTestCase()42     static void SetUpTestCase()
43     {
44     }
45 
TearDownTestCase()46     static void TearDownTestCase()
47     {
48     }
49 
SetUp()50     virtual void SetUp()
51     {
52     }
53 
TearDown()54     virtual void TearDown()
55     {
56     }
57 };
58 
HWTEST_F(SchedulerTest, taskstate_test, TestSize.Level1)59 HWTEST_F(SchedulerTest, taskstate_test, TestSize.Level1)
60 {
61     std::queue<std::unique_ptr<SCPUEUTask>> tasks;
62 
63     std::vector<TaskState::State> produceStatus;
64     std::vector<TaskState::State> consumeStatus;
65 
66 #if (TASKSTAT_LOG_ENABLE == 1)
67     std::array<uint64_t, static_cast<size_t>(TaskState::MAX)> expectCount;
68 
69     // record previous test units count
70     for (auto state = TaskState::PENDING; state != TaskState::MAX; ++(size_t&)state) {
71         expectCount[static_cast<size_t>(state)] = TaskManager::Instance().GetCount(state);
72     }
73 
74     // expect non-exited state count equal zero
75     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::PENDING)], 0);
76     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], 0);
77     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::RUNNING)], 0);
78     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::BLOCKED)], 0);
79 
80     auto increCount = [&expectCount](TaskState::State state) { ++expectCount[static_cast<size_t>(state)]; };
81 
82     auto decreCount = [&expectCount](TaskState::State state) {
83         if (expectCount[static_cast<size_t>(state)] > 0) {
84             --expectCount[static_cast<size_t>(state)];
85         }
86     };
87 #endif
88     auto setState = [&](CPUEUTask* task) {
89         consumeStatus.emplace_back(task->state());
90         return true;
91     };
92 
93     auto getNextState = [](TaskState::State state) {
94         switch (state) {
95             case TaskState::PENDING:
96                 return TaskState::READY;
97             case TaskState::READY:
98                 return TaskState::RUNNING;
99             case TaskState::RUNNING:
100                 return TaskState::BLOCKED;
101             case TaskState::BLOCKED:
102                 return TaskState::EXITED;
103             default:
104                 break;
105         }
106         return TaskState::MAX;
107     };
108 
109     TaskState::RegisterOps(TaskState::READY, setState);
110     TaskState::RegisterOps(TaskState::RUNNING, setState);
111     TaskState::RegisterOps(TaskState::BLOCKED, setState);
112     TaskState::RegisterOps(TaskState::EXITED, setState);
113 
114     task_attr_private task_attr;
115     task_attr.name_ = "root";
116     auto root = std::make_unique<SCPUEUTask>(
117         &task_attr, nullptr, 0);
118     for (int i = 1; i <= 1000; ++i) {
119         task_attr_private task_attr;
120         task_attr.name_ = "i";
121         tasks.push(std::make_unique<SCPUEUTask>(
122             &task_attr, root.get(), i));
123     }
124 
125     while (!tasks.empty()) {
126         auto task = std::move(tasks.front());
127         tasks.pop();
128 
129         auto state = getNextState(task->state());
130         if (state == TaskState::MAX) {
131             continue;
132         }
133 
134         produceStatus.emplace_back(state);
135 
136         task->UpdateState(state);
137 
138 #if (TASKSTAT_LOG_ENABLE == 1)
139         auto preState = task->state.PreState();
140         auto curState = task->state.CurState();
141 
142         decreCount(preState);
143         increCount(curState);
144 
145         EXPECT_EQ(expectCount[static_cast<size_t>(preState)], TaskManager::Instance().GetCount(preState));
146         EXPECT_EQ(expectCount[static_cast<size_t>(curState)], TaskManager::Instance().GetCount(curState));
147 #endif
148 
149         tasks.push(std::move(task));
150     }
151 
152 #if (TRACE_TASKSTAT_LOG_ENABLE == 1)
153     EXPECT_EQ(
154         expectCount[static_cast<size_t>(TaskState::PENDING)], TaskManager::Instance().GetCount(TaskState::PENDING));
155     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], TaskManager::Instance().GetCount(TaskState::READY));
156     EXPECT_EQ(
157         expectCount[static_cast<size_t>(TaskState::RUNNING)], TaskManager::Instance().GetCount(TaskState::RUNNING));
158     EXPECT_EQ(
159         expectCount[static_cast<size_t>(TaskState::BLOCKED)], TaskManager::Instance().GetCount(TaskState::BLOCKED));
160     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::EXITED)], TaskManager::Instance().GetCount(TaskState::EXITED));
161 #endif
162 
163     EXPECT_EQ(produceStatus.size(), consumeStatus.size());
164 
165     int size = produceStatus.size();
166     for (int i = 0; i < size; ++i) {
167         EXPECT_EQ(produceStatus[i], consumeStatus[i]);
168     }
169 }
170 
HWTEST_F(SchedulerTest, taskstateCount_test, TestSize.Level1)171 HWTEST_F(SchedulerTest, taskstateCount_test, TestSize.Level1)
172 {
173     SCPUEUTask* task1 = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
174     SCPUEUTask *task2 = new SCPUEUTask(nullptr, task1, 0, QoS());
175     TaskManager::Instance().TaskStateCount(task2);
176 }
177 
HWTEST_F(SchedulerTest, ffrt_task_runqueue_test, TestSize.Level1)178 HWTEST_F(SchedulerTest, ffrt_task_runqueue_test, TestSize.Level1)
179 {
180     ffrt::FIFOQueue *fifoqueue = new ffrt::FIFOQueue();
181     int aimnum = 10;
182     for (int i = 0; i < aimnum ; i++) {
183         SCPUEUTask* task = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
184         fifoqueue->EnQueue(task);
185     }
186     EXPECT_EQ(fifoqueue->Size(), aimnum);
187     EXPECT_EQ(fifoqueue->Empty(), false);
188 }
189 
HWTEST_F(SchedulerTest, ffrt_scheduler_test, TestSize.Level1)190 HWTEST_F(SchedulerTest, ffrt_scheduler_test, TestSize.Level1)
191 {
192     ffrt::SFFRTScheduler *sffrtscheduler = new ffrt::SFFRTScheduler();
193     LinkedList* node = new LinkedList();
194     QoS qos;
195     EXPECT_EQ(sffrtscheduler->InsertNode(node, qos), true);
196     EXPECT_EQ(sffrtscheduler->RemoveNode(node, qos), true);
197 
198     delete node;
199 }
200