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 <gtest/gtest.h>
17 #include <gmock/gmock.h>
18 #ifndef WITH_NO_MOCKER
19 #include <mockcpp/mockcpp.hpp>
20 #endif
21 #define private public
22 #define protected public
23 #include <eu/scpu_monitor.h>
24 #include <util/worker_monitor.h>
25 #undef private
26 #undef protected
27
28 #include "qos.h"
29 #include "../common.h"
30
31 #ifndef FFRT_GITEE
32 #include "cpp/ffrt_dynamic_graph.h"
33 #include "c/ffrt_dynamic_graph.h"
34 #endif
35
36 using namespace testing;
37 #ifdef HWTEST_TESTING_EXT_ENABLE
38 using namespace testing::ext;
39 #endif
40 using namespace ffrt;
41 using ::testing::Return;
42
43 #ifndef FFRT_GITEE
44 namespace {
45 // 返回当前环境是软化还是硬化
CheckSoftwareEnv()46 bool CheckSoftwareEnv()
47 {
48 return (ffrt_hcs_get_capability(FFRT_HW_DYNAMIC_XPU_NORMAL) == 0) ? true : false;
49 }
50 }
51 #endif
52
53 class WorkerManager {
54 public:
IncWorker(const QoS & qos)55 virtual bool IncWorker(const QoS& qos)
56 {
57 return true;
58 }
WakeupWorkers(const QoS & qos)59 virtual void WakeupWorkers(const QoS& qos)
60 {
61 }
GetTaskCount(const QoS & qos)62 virtual int GetTaskCount(const QoS& qos)
63 {
64 return 0;
65 }
GetWorkerCount(const QoS & qos)66 virtual int GetWorkerCount(const QoS& qos)
67 {
68 return 0;
69 }
70 };
71
72 class MockWorkerManager : public WorkerManager {
73 public:
MockWorkerManager()74 MockWorkerManager()
75 {
76 }
~MockWorkerManager()77 ~MockWorkerManager()
78 {
79 }
80 MOCK_METHOD1(IncWorker, bool(const QoS&));
81 MOCK_METHOD1(WakeupWorkers, void(const QoS&));
82 MOCK_METHOD1(GetTaskCount, int(const QoS&));
83 MOCK_METHOD1(GetWorkerCount, int(const QoS&));
84 };
85
86 class CpuMonitorTest : public testing::Test {
87 protected:
SetUpTestCase()88 static void SetUpTestCase()
89 {
90 }
91
TearDownTestCase()92 static void TearDownTestCase()
93 {
94 }
95
SetUp()96 void SetUp() override
97 {
98 }
99
TearDown()100 void TearDown() override
101 {
102 }
103 };
104
105 /**
106 * 测试用例名称:set_sched_mode
107 * 测试用例描述:验证设置EU调度模式的接口
108 * 预置条件:
109 * 操作步骤:设置不同的调度模式,并通过get接口与设置值对比
110 * 预期结果:设置成功
111 */
112 #ifndef FFRT_GITEE
113 HWTEST_F(CpuMonitorTest, set_sched_mode, TestSize.Level1)
114 {
115 if (CheckSoftwareEnv()) {
116 return;
117 }
118 ffrt::sched_mode_type sched_type = ffrt::CPUManagerStrategy::GetSchedMode(ffrt::QoS(ffrt::qos_default));
119 EXPECT_EQ(static_cast<int>(sched_type), static_cast<int>(ffrt::sched_mode_type::sched_default_mode));
120
121 ffrt_set_sched_mode(ffrt::QoS(ffrt::qos_default), ffrt_sched_energy_saving_mode);
122 sched_type = ffrt::CPUManagerStrategy::GetSchedMode(ffrt::QoS(ffrt::qos_default));
123 EXPECT_EQ(static_cast<int>(sched_type), static_cast<int>(ffrt::sched_mode_type::sched_default_mode));
124
125 ffrt_set_sched_mode(ffrt::QoS(ffrt::qos_default), ffrt_sched_performance_mode);
126 sched_type = ffrt::CPUManagerStrategy::GetSchedMode(ffrt::QoS(ffrt::qos_default));
127 EXPECT_EQ(static_cast<int>(sched_type), static_cast<int>(ffrt::sched_mode_type::sched_performance_mode));
128
129 ffrt_set_sched_mode(ffrt::QoS(ffrt::qos_default), ffrt_sched_default_mode);
130 }
131 #endif
132
133 HWTEST_F(CpuMonitorTest, monitor_notify_test, TestSize.Level1)
134 {
135 testing::NiceMock<MockWorkerManager> mWmanager;
136 QoS qos(qos_default);
137 SCPUMonitor wmonitor({
138 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
139 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
140 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
141 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1),
142 SCPUMonitor::HandleTaskNotifyDefault});
143
144 (void)wmonitor.GetMonitorTid();
145
146 EXPECT_CALL(mWmanager, GetTaskCount(qos)).WillRepeatedly(Return(0));
147
148 wmonitor.Notify(QoS(static_cast<int>(qos_default)), TaskNotifyType::TASK_ADDED);
149 wmonitor.Notify(QoS(static_cast<int>(qos_default)), TaskNotifyType::TASK_PICKED);
150
151 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 0);
152 EXPECT_CALL(mWmanager, GetTaskCount(qos)).WillRepeatedly(Return(1));
153 EXPECT_CALL(mWmanager, GetWorkerCount(qos)).WillRepeatedly(Return(5));
154
155 for (uint32_t idx = 1; idx <= 5; idx++) {
156 wmonitor.Notify(QoS(static_cast<int>(qos_default)), TaskNotifyType::TASK_ADDED);
157 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, idx);
158 }
159
160 wmonitor.Notify(QoS(static_cast<int>(qos_default)), TaskNotifyType::TASK_PICKED);
161 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 5);
162 }
163
164 // 批量唤醒worker
165 HWTEST_F(CpuMonitorTest, monitor_notify_workers_test, TestSize.Level1)
166 {
167 testing::NiceMock<MockWorkerManager> mWmanager;
168 SCPUMonitor wmonitor({
169 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
170 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
171 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
172 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1)});
173
174 QoS qosDefault(qos_default);
175 wmonitor.NotifyWorkers(qosDefault, 3);
176 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 3);
177 wmonitor.NotifyWorkers(qosDefault, 2);
178 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 5);
179 wmonitor.NotifyWorkers(qosDefault, 5);
180 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 8);
181
182 wmonitor.ctrlQueue[qos_default].executionNum = 4;
183 wmonitor.ctrlQueue[qos_default].sleepingWorkerNum = 4;
184 wmonitor.NotifyWorkers(qosDefault, 5);
185 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 4);
186
187 notify_workers(qos_default, 1);
188 }
189
190 HWTEST_F(CpuMonitorTest, SubmitTask_test, TestSize.Level1)
191 {
192 WorkerMonitor workermonitor;
193 workermonitor.skipSampling_ = true;
194 workermonitor.SubmitTask();
195
196 EXPECT_EQ(workermonitor.skipSampling_, true);
197 }
198
199 HWTEST_F(CpuMonitorTest, SubmitMemReleaseTask_test, TestSize.Level1)
200 {
201 WorkerMonitor workermonitor;
202 workermonitor.skipSampling_ = true;
203 workermonitor.SubmitMemReleaseTask();
204
205 EXPECT_EQ(workermonitor.skipSampling_, true);
206 }
207
208 HWTEST_F(CpuMonitorTest, RecordKeyInfo_test, TestSize.Level1)
209 {
210 WorkerMonitor workermonitor;
211 const std::string& dumpInfo = "";
212 workermonitor.RecordKeyInfo(dumpInfo);
213
214 EXPECT_EQ(workermonitor.skipSampling_, false);
215 }
216
217 HWTEST_F(CpuMonitorTest, CheckWorkerStatus_test, TestSize.Level1)
218 {
219 WorkerMonitor workermonitor;
220 workermonitor.skipSampling_ = true;
221 workermonitor.CheckWorkerStatus();
222
223 EXPECT_EQ(workermonitor.skipSampling_, true);
224 }
225
226 HWTEST_F(CpuMonitorTest, qosmap_test, TestSize.Level1)
227 {
228 int qos = -1;
229 EXPECT_EQ(-1, QoSMap(qos));
230
231 qos = 300;
232 }
233
234 /*
235 * 测试用例名称 ;worker_escape_test
236 * 测试用例描述 :测试逃生惩罚功能
237 * 预置条件 :1、对CPUMonitor的IncWorker、WakeupWorkers、GetTaskCount方法进行打桩
238 * 2、对CPUMonitor的GetRunningNum方法进行打桩,使其始终返回0
239 * 3、将CPUMonitor的executionNum设置为16
240 * 操作步骤 :1、调用enable_worker_escape传入非法入参
241 * 2、调用enable_worker_escape
242 * 3、再次调用enable_worker_escape
243 * 4、调用CPUMonitor的Poke方法
244 * 预期结果 :1、传入非法入参返回错误码
245 * 2、重复调用返回错误码
246 * 3、逃生惩罚功能生效
247 */
248 HWTEST_F(CpuMonitorTest, worker_escape_test, TestSize.Level1)
249 {
250 #ifdef WITH_NO_MOCKER
251 ffrt::disable_worker_escape();
252
253 // 非法入参
254 EXPECT_EQ(ffrt::enable_worker_escape(0), 1);
255 EXPECT_EQ(ffrt::enable_worker_escape(), 0);
256 // 不允许重复调用
257 EXPECT_EQ(ffrt::enable_worker_escape(), 1);
258 #else
259 int incWorkerNum = 0;
260 int wakedWorkerNum = 0;
261 testing::NiceMock<MockWorkerManager> mWmanager;
262 SCPUMonitor wmonitor({
263 [&] (const QoS& qos) { incWorkerNum++; return true; },
264 [&] (const QoS& qos) { wakedWorkerNum++; },
265 [] (const QoS& qos) { return 1; },
266 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1) });
267 MOCKER_CPP(&SCPUMonitor::GetRunningNum).stubs().will(returnValue(static_cast<size_t>(0)));
268
269 ffrt::disable_worker_escape();
270 // 非法入参
271 EXPECT_EQ(ffrt::enable_worker_escape(0), 1);
272 EXPECT_EQ(ffrt::enable_worker_escape(), 0);
273 // 不允许重复调用
274 EXPECT_EQ(ffrt::enable_worker_escape(), 1);
275
276 wmonitor.escapeMgr_.enableEscape_ = true;
277 WorkerCtrl& workerCtrl = wmonitor.ctrlQueue[2];
278 workerCtrl.executionNum = 16;
279
280 wmonitor.Poke(2, 1, TaskNotifyType::TASK_ADDED);
281 usleep(100 * 1000);
282 EXPECT_EQ(incWorkerNum, 1);
283
284 wmonitor.ops.GetTaskCount = [&] (const QoS& qos) { workerCtrl.sleepingWorkerNum = 1; return 1; };
285 wmonitor.Poke(2, 1, TaskNotifyType::TASK_ADDED);
286 usleep(100 * 1000);
287 EXPECT_EQ(wakedWorkerNum, 1);
288 #endif
289 }
290
291 #ifndef FFRT_GITEE
292 /**
293 * @tc.name: TryDestroy
294 * @tc.desc: Test whether the RollbackDestroy interface are normal.
295 * @tc.type: FUNC
296 *
297 *
298 */
299 HWTEST_F(CpuMonitorTest, monitor_worker_trydestroy_test, TestSize.Level1)
300 {
301 testing::NiceMock<MockWorkerManager> mWmanager;
302 SCPUMonitor wmonitor({
303 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
304 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
305 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
306 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1) });
307
308 QoS qosDefault(qos_default);
309 wmonitor.ctrlQueue[qos_default].sleepingWorkerNum = 1;
310 wmonitor.TryDestroy(qosDefault);
311 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].sleepingWorkerNum, 0);
312 }
313
314 /**
315 * @tc.name: RollbackDestroy
316 * @tc.desc: Test whether the RollbackDestroy interface are normal.
317 * @tc.type: FUNC
318 *
319 *
320 */
321 HWTEST_F(CpuMonitorTest, monitor_worker_rollbackdestroy_test, TestSize.Level1)
322 {
323 testing::NiceMock<MockWorkerManager> mWmanager;
324 SCPUMonitor wmonitor({
325 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
326 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
327 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
328 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1) });
329
330 QoS qosDefault(qos_default);
331 wmonitor.ctrlQueue[qos_default].executionNum = 0;
332 wmonitor.RollbackDestroy(qosDefault, true);
333 EXPECT_EQ(wmonitor.ctrlQueue[qos_default].executionNum, 1);
334 }
335
336 /*
337 * 测试用例名称 ;set_worker_num_test
338 * 测试用例描述 :测试传入0-QOS_WORKER_MAXNUM之间worker数量的情况
339 * 操作步骤 :传入worker数量为4
340 * 预期结果 :预期成功
341 */
342 HWTEST_F(CpuMonitorTest, set_worker_num_test, TestSize.Level1)
343 {
344 testing::NiceMock<MockWorkerManager> mWmanager;
345 SCPUMonitor wmonitor({
346 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
347 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
348 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
349 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1) });
350
351 int ret = wmonitor.SetWorkerMaxNum(qos(2), 4);
352 wmonitor.WakeupSleep(QoS(5), true);
353 wmonitor.RollbackDestroy(QoS(5), false);
354
355 EXPECT_EQ(ret, 0);
356 }
357
358 HWTEST_F(CpuMonitorTest, total_count_test, TestSize.Level1)
359 {
360 testing::NiceMock<MockWorkerManager> mWmanager;
361 SCPUMonitor wmonitor({
362 std::bind(&MockWorkerManager::IncWorker, &mWmanager, std::placeholders::_1),
363 std::bind(&MockWorkerManager::WakeupWorkers, &mWmanager, std::placeholders::_1),
364 std::bind(&MockWorkerManager::GetTaskCount, &mWmanager, std::placeholders::_1),
365 std::bind(&MockWorkerManager::GetWorkerCount, &mWmanager, std::placeholders::_1) });
366
367 int ret = wmonitor.TotalCount(qos(2));
368
369 EXPECT_NE(ret, -1);
370 }
371
372 #endif