• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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