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 "../common.h"
31 
32 using namespace std;
33 using namespace testing;
34 #ifdef HWTEST_TESTING_EXT_ENABLE
35 using namespace testing::ext;
36 #endif
37 using namespace ffrt;
38 
39 class SchedulerTest : public testing::Test {
40 protected:
SetUpTestCase()41     static void SetUpTestCase()
42     {
43     }
44 
TearDownTestCase()45     static void TearDownTestCase()
46     {
47     }
48 
SetUp()49     virtual void SetUp()
50     {
51     }
52 
TearDown()53     virtual void TearDown()
54     {
55     }
56 };
57 
58 HWTEST_F(SchedulerTest, taskstate_test, TestSize.Level1)
59 {
60     std::queue<std::unique_ptr<SCPUEUTask>> tasks;
61 
62     std::vector<TaskState::State> produceStatus;
63     std::vector<TaskState::State> consumeStatus;
64 
65 #if (TASKSTAT_LOG_ENABLE == 1)
66     std::array<uint64_t, static_cast<size_t>(TaskState::MAX)> expectCount;
67 
68     // record previous test units count
69     for (auto state = TaskState::PENDING; state != TaskState::MAX; ++(size_t&)state) {
70         expectCount[static_cast<size_t>(state)] = TaskManager::Instance().GetCount(state);
71     }
72 
73     // expect non-exited state count equal zero
74     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::PENDING)], 0);
75     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], 0);
76     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::RUNNING)], 0);
77     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::BLOCKED)], 0);
78 
__anone6bee3b60102(TaskState::State state) 79     auto increCount = [&expectCount](TaskState::State state) { ++expectCount[static_cast<size_t>(state)]; };
80 
__anone6bee3b60202(TaskState::State state) 81     auto decreCount = [&expectCount](TaskState::State state) {
82         if (expectCount[static_cast<size_t>(state)] > 0) {
83             --expectCount[static_cast<size_t>(state)];
84         }
85     };
86 #endif
__anone6bee3b60302(CPUEUTask* task) 87     auto setState = [&](CPUEUTask* task) {
88         consumeStatus.emplace_back(task->state());
89         return true;
90     };
91 
__anone6bee3b60402(TaskState::State state) 92     auto getNextState = [](TaskState::State state) {
93         switch (state) {
94             case TaskState::PENDING:
95                 return TaskState::READY;
96             case TaskState::READY:
97                 return TaskState::RUNNING;
98             case TaskState::RUNNING:
99                 return TaskState::BLOCKED;
100             case TaskState::BLOCKED:
101                 return TaskState::EXITED;
102             default:
103                 break;
104         }
105         return TaskState::MAX;
106     };
107 
108     TaskState::RegisterOps(TaskState::READY, setState);
109     TaskState::RegisterOps(TaskState::RUNNING, setState);
110     TaskState::RegisterOps(TaskState::BLOCKED, setState);
111     TaskState::RegisterOps(TaskState::EXITED, setState);
112 
113     task_attr_private task_attr;
114     task_attr.name_ = "root";
115     auto root = std::make_unique<SCPUEUTask>(
116         &task_attr, nullptr, 0);
117     for (int i = 1; i <= 1000; ++i) {
118         task_attr_private task_attr;
119         task_attr.name_ = "i";
120         tasks.push(std::make_unique<SCPUEUTask>(
121             &task_attr, root.get(), i));
122     }
123 
124     while (!tasks.empty()) {
125         auto task = std::move(tasks.front());
126         tasks.pop();
127 
128         auto state = getNextState(task->state());
129         if (state == TaskState::MAX) {
130             continue;
131         }
132 
133         produceStatus.emplace_back(state);
134 
135         task->UpdateState(state);
136 
137 #if (TASKSTAT_LOG_ENABLE == 1)
138         auto preState = task->state.PreState();
139         auto curState = task->state.CurState();
140 
141         decreCount(preState);
142         increCount(curState);
143 
144         EXPECT_EQ(expectCount[static_cast<size_t>(preState)], TaskManager::Instance().GetCount(preState));
145         EXPECT_EQ(expectCount[static_cast<size_t>(curState)], TaskManager::Instance().GetCount(curState));
146 #endif
147 
148         tasks.push(std::move(task));
149     }
150 
151 #if (TRACE_TASKSTAT_LOG_ENABLE == 1)
152     EXPECT_EQ(
153         expectCount[static_cast<size_t>(TaskState::PENDING)], TaskManager::Instance().GetCount(TaskState::PENDING));
154     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::READY)], TaskManager::Instance().GetCount(TaskState::READY));
155     EXPECT_EQ(
156         expectCount[static_cast<size_t>(TaskState::RUNNING)], TaskManager::Instance().GetCount(TaskState::RUNNING));
157     EXPECT_EQ(
158         expectCount[static_cast<size_t>(TaskState::BLOCKED)], TaskManager::Instance().GetCount(TaskState::BLOCKED));
159     EXPECT_EQ(expectCount[static_cast<size_t>(TaskState::EXITED)], TaskManager::Instance().GetCount(TaskState::EXITED));
160 #endif
161 
162     EXPECT_EQ(produceStatus.size(), consumeStatus.size());
163 
164     int size = produceStatus.size();
165     for (int i = 0; i < size; ++i) {
166         EXPECT_EQ(produceStatus[i], consumeStatus[i]);
167     }
168 }
169 
170 HWTEST_F(SchedulerTest, taskstateCount_test, TestSize.Level1)
171 {
172     SCPUEUTask* task1 = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
173     SCPUEUTask *task2 = new SCPUEUTask(nullptr, task1, 0, QoS());
174     TaskManager::Instance().TaskStateCount(task2);
175 }
176