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 <random>
18 #include <cinttypes>
19 #include "ffrt_inner.h"
20 #include "util.h"
21 #include "c/deadline.h"
22 #include "c/executor_task.h"
23 #include "tm/scpu_task.h"
24 #include "dfx/log/ffrt_log_api.h"
25 #include "dm/sdependence_manager.h"
26 #ifndef WITH_NO_MOCKER
27 extern "C" int ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr *attr);
28 #endif
29 #include "../common.h"
30
31 using namespace std;
32 using namespace testing;
33 #ifdef HWTEST_TESTING_EXT_ENABLE
34 using namespace testing::ext;
35 #endif
36
37 class DependencyTest : public testing::Test {
38 protected:
SetUpTestCase()39 static void SetUpTestCase()
40 {
41 }
42
TearDownTestCase()43 static void TearDownTestCase()
44 {
45 }
46
SetUp()47 void SetUp() override
48 {
49 }
50
TearDown()51 void TearDown() override
52 {
53 }
54 };
55
56 HWTEST_F(DependencyTest, dependency_success_01, TestSize.Level1)
57 {
58 int x = 0;
__anonbee5675e0302() 59 ffrt::submit([&]() { x = 2; }, {}, {&x});
__anonbee5675e0602() 60 ffrt::submit([&]() { x = x * 3; }, {&x}, {});
61 ffrt::wait();
62 EXPECT_EQ(x, 6);
63 }
64
65 HWTEST_F(DependencyTest, update_qos_success_02, TestSize.Level1)
66 {
67 int ret = ffrt_task_attr_init(nullptr);
68 EXPECT_EQ(ret, -1);
69 ffrt_task_attr_get_name(nullptr);
70 ffrt_task_attr_set_name(nullptr, "A");
71 ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
72 ffrt_task_attr_get_qos(nullptr);
73 ffrt_task_attr_destroy(nullptr);
74 ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
75 ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
__anonbee5675e0702null76 ffrt::submit([] {
77 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
78 printf("id is %" PRIu64 "\n", ffrt::this_task::get_id());
79 });
80 ffrt_this_task_get_id();
81 ffrt::wait();
82 ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_user_initiated));
83 #ifndef WITH_NO_MOCKER
84 ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), nullptr);
85 #endif
86 }
87
88 HWTEST_F(DependencyTest, update_qos_success_03, TestSize.Level1)
89 {
90 int ret = ffrt_task_attr_init(nullptr);
91 EXPECT_EQ(ret, -1);
__anonbee5675e0802null92 ffrt::submit([] {
93 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
94 });
95 ffrt_restore_qos_config();
96 }
97
98 HWTEST_F(DependencyTest, update_qos_success_04, TestSize.Level1)
99 {
100 int ret = ffrt_task_attr_init(nullptr);
101 EXPECT_EQ(ret, -1);
__anonbee5675e0902null102 ffrt::submit([] {
103 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
104 });
105 int ret2 = ffrt_set_cpu_worker_max_num(static_cast<int>(ffrt::qos_user_initiated), 4);
106 EXPECT_EQ(ret2, 0);
107 }
108
109 HWTEST_F(DependencyTest, update_qos_success_05, TestSize.Level1)
110 {
111 int x = 0;
112 int ret = ffrt_task_attr_init(nullptr);
113 EXPECT_EQ(ret, -1);
114 ffrt_task_attr_get_name(nullptr);
115 ffrt_task_attr_set_name(nullptr, "A");
116 ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
117 ffrt_task_attr_get_qos(nullptr);
118 ffrt_task_attr_destroy(nullptr);
119 ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
120 ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
__anonbee5675e0a02null121 ffrt::submit([&] {
122 x++;
123 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
124 printf("id is %" PRIu64 "\n", ffrt::this_task::get_id());
125 });
126 ffrt_this_task_get_id();
127 ffrt::wait();
128 ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_user_initiated));
129 #ifndef WITH_NO_MOCKER
130 ffrt_os_sched_attr attr = {100, 10, 99, 99, 9, "2-3"};
131 ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), &attr);
132 #endif
133 EXPECT_EQ(x, 1);
134 }
135
136 HWTEST_F(DependencyTest, update_qos_failed_01, TestSize.Level1)
137 {
138 int x = 0;
139 int ret = ffrt_task_attr_init(nullptr);
140 EXPECT_EQ(ret, -1);
141 ffrt_task_attr_get_name(nullptr);
142 ffrt_task_attr_set_name(nullptr, "A");
143 ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
144 ffrt_task_attr_get_qos(nullptr);
145 ffrt_task_attr_destroy(nullptr);
146 ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
147 ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
__anonbee5675e0b02null148 ffrt::submit([&] {
149 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
150 printf("id is %" PRIu64 "\n", ffrt::this_task::get_id());
151 int ret1 = ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_default));
152 EXPECT_EQ(ret1, 0);
153 x++;
154 });
155 ffrt_this_task_get_id();
156 ffrt::wait();
157 #ifndef WITH_NO_MOCKER
158 ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), nullptr);
159 #endif
160 EXPECT_EQ(x, 1);
161 }
162
163 HWTEST_F(DependencyTest, update_qos_failed_02, TestSize.Level1)
164 {
165 int ret = ffrt_task_attr_init(nullptr);
166 EXPECT_EQ(ret, -1);
__anonbee5675e0c02null167 ffrt::submit([] {
168 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
169 });
170 int ret1 = ffrt_set_cpu_worker_max_num(static_cast<int>(ffrt::qos_inherit), 4);
171 EXPECT_EQ(ret1, -1);
172 }
173
174 /*
175 * 测试用例名称 :set_worker_min_num_test
176 * 测试用例描述 :测试传入0个线程的情况
177 * 操作步骤 :测试传入0个线程
178 * 预期结果 :预期失败
179 */
180 HWTEST_F(DependencyTest, set_worker_min_num_test, TestSize.Level1)
181 {
182 int ret = ffrt_task_attr_init(nullptr);
183 EXPECT_EQ(ret, -1);
__anonbee5675e0d02null184 ffrt::submit([] {
185 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
186 });
187 int ret2 = ffrt_set_cpu_worker_max_num(static_cast<int>(ffrt::qos_user_initiated), 0);
188 EXPECT_EQ(ret2, -1);
189 }
190
191 /*
192 * 测试用例名称 :set_worker_max_num_test
193 * 测试用例描述 :测试传入超过最大线程数量的情况
194 * 操作步骤 :测试传入160个线程
195 * 预期结果 :预期失败
196 */
197 HWTEST_F(DependencyTest, set_worker_max_num_test, TestSize.Level1)
198 {
199 int ret = ffrt_task_attr_init(nullptr);
200 EXPECT_EQ(ret, -1);
__anonbee5675e0e02null201 ffrt::submit([] {
202 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
203 });
204
205 int ret1 = ffrt_set_cpu_worker_max_num(static_cast<int>(ffrt::qos_user_initiated), 160);
206 EXPECT_EQ(ret1, -1);
207 }
208
209 HWTEST_F(DependencyTest, ffrt_task_attr_get_name_set_notify_test, TestSize.Level1)
210 {
211 int x = 0;
212 int ret = ffrt_task_attr_init(nullptr);
213 EXPECT_EQ(ret, -1);
214 ffrt_task_attr_t attr;
215 attr.storage[0] = 12345;
216 ffrt_task_attr_set_name(nullptr, "A");
217 ffrt_task_attr_get_name(&attr);
218 ffrt_task_attr_set_notify_worker(&attr, true);
219 ffrt_task_attr_set_notify_worker(nullptr, true);
220 ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
221 ffrt_task_attr_get_qos(nullptr);
222 ffrt_task_attr_destroy(nullptr);
223 ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
224 ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
__anonbee5675e0f02null225 ffrt::submit([&] {
226 printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
227 printf("id is %" PRIu64 "\n", ffrt::this_task::get_id());
228 int ret1 = ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_default));
229 EXPECT_EQ(ret1, 0);
230 x++;
231 });
232 ffrt_this_task_get_id();
233 ffrt::wait();
234 ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), nullptr);
235 EXPECT_EQ(x, 1);
236 }
237
238 HWTEST_F(DependencyTest, executor_task_submit_success_cancel_01, TestSize.Level1)
239 {
240 ffrt_task_attr_t attr;
241 static ffrt_executor_task_t work;
242 work.wq[0] = &work.wq;
243 work.wq[1] = &work.wq;
244 work.type = reinterpret_cast<uintptr_t>(&attr);
245 ffrt_executor_task_submit(nullptr, nullptr);
246
247 ffrt_executor_task_submit(&work, &attr);
248
249 int ret = ffrt_executor_task_cancel(nullptr, static_cast<int>(ffrt::qos_user_initiated));
250 EXPECT_EQ(ret, 0);
251 }
252
253 HWTEST_F(DependencyTest, executor_task_submit_cancel_02, TestSize.Level1)
254 {
255 ffrt_task_attr_t attr;
256 ffrt_task_attr_init(&attr);
257 ffrt_executor_task_t work;
258 work.type = reinterpret_cast<uintptr_t>(&attr);
259
260 ffrt_task_attr_set_qos(&attr, static_cast<int>(ffrt::qos_user_initiated));
261 ffrt_executor_task_submit(&work, &attr);
262 usleep(10000);
263 int cancelled = ffrt_executor_task_cancel(&work, static_cast<int>(ffrt::qos_user_initiated));
264 EXPECT_EQ(cancelled, 0);
265
266 ffrt_task_attr_destroy(&attr);
267 }
268
269 static std::atomic_int uv_sleep = 0;
ffrt_work_sleep(ffrt_executor_task_t * data,ffrt_qos_t qos)270 void ffrt_work_sleep(ffrt_executor_task_t* data, ffrt_qos_t qos)
271 {
272 usleep(1000);
273 uv_sleep++;
274 }
275
init_once_sleep(void)276 static void init_once_sleep(void)
277 {
278 uv_sleep = 0;
279 ffrt_executor_task_register_func(ffrt_work_sleep, ffrt_uv_task);
280 }
281
282 /*
283 * 测试用例名称:executor_task_submit_cancel_03
284 * 测试用例描述:uv任务正确取消
285 * 预置条件 :无
286 * 操作步骤 :1、调用注册接口,给uv任务注册一个耗时函数
287 2、提交taskCount个任务
288 3、随机取消taskCount次任务
289 * 预期结果 :1、能够取消至少一个uv任务
290 2、取消的任务数+已执行的任务数=总提交任务数
291 3、取消的任务数>0,已执行的任务数<总提交任务数
292 */
293 HWTEST_F(DependencyTest, executor_task_submit_cancel_03, TestSize.Level1)
294 {
295 int taskCount = 10000;
296 ffrt_task_attr_t attr;
297 ffrt_task_attr_init(&attr);
298 ffrt_executor_task_t work[taskCount];
299 init_once_sleep();
300 std::atomic_int cancelCount {0};
301 ffrt::task_attr task_attr;
302 task_attr.qos(ffrt::qos_background);
303 std::random_device rd;
304 std::mt19937 gen(rd());
305 std::uniform_int_distribution<> dis(0, taskCount - 1);
306 ffrt_task_attr_set_qos(&attr, static_cast<int>(ffrt::qos_user_initiated));
__anonbee5675e1002() 307 auto tryCancel = [&]() {
308 for (int i = taskCount - 1; i >= 0; --i) {
309 cancelCount += ffrt_executor_task_cancel(&work[dis(gen)], static_cast<int>(ffrt::qos_user_initiated));
310 }
311 };
312 for (int i = 0; i < taskCount; i++) {
313 work[i].type = ffrt_uv_task;
314 ffrt_executor_task_submit(&work[i], &attr);
315 }
316 ffrt::submit(tryCancel, {}, {}, task_attr);
317 ffrt::submit(tryCancel, {}, {}, task_attr);
318 ffrt::wait();
319 sleep(2);
320 EXPECT_LT(uv_sleep, taskCount);
321 EXPECT_GT(uv_sleep, 0);
322 EXPECT_GE(uv_sleep + cancelCount, taskCount);
323 ffrt_task_attr_destroy(&attr);
324 }
325
326 HWTEST_F(DependencyTest, update_trace_tag_task_attr_success, TestSize.Level1)
327 {
328 ffrt::set_trace_tag("TASK A");
329 ffrt::clear_trace_tag();
330
331 ffrt::task_attr tmpTask;
332 tmpTask.name("Task A");
333 tmpTask.qos(static_cast<int>(ffrt::qos_user_initiated));
334
335 EXPECT_EQ(ffrt_task_attr_get_qos(&tmpTask), ffrt::qos_user_initiated);
336 }
337
338 HWTEST_F(DependencyTest, sample_pingpong_pipe_interval_checkpoint, TestSize.Level1)
339 {
340 int loops = 5;
341 int frame_num = 2;
342
343 if (getenv("LOOP_NUM")) {
344 loops = atoi(getenv("LOOP_NUM"));
345 }
346 if (getenv("FRAME_NUM")) {
347 frame_num = atoi(getenv("FRAME_NUM"));
348 }
349
__anonbee5675e1302() 350 ffrt::submit([&]() { stall_us(10); }, {}, {});
351
352 auto it = ffrt::qos_interval_create(16, static_cast<int>(ffrt::qos_user_interactive));
353 for (int loop = 0; loop < loops; loop++) {
354 constexpr int FRAME_NUM = 3;
355 constexpr uint32_t BUFFER_NUM = 2;
356 int x0[FRAME_NUM];
357 int x1[BUFFER_NUM];
358 int x2[BUFFER_NUM];
359 int x3[FRAME_NUM];
360
361 int stalls[10][4] = {
362 {2000, 6000, 8000, 8000 + 6000 + 2000}, // 0
363 {2125, 6375, 8500, 8500 + 6375 + 2125}, // 1
364 {2222, 6666, 8888, 8888 + 6666 + 2222}, // 2
365 {2250, 6750, 9000, 9000 + 6750 + 2250}, // 3
366 {2375, 7125, 9500, 9500 + 7125 + 2375}, // 4
367 {2500, 7500, 10000, 10000 + 7500 + 2500}, // 5
368 {1875, 5625, 7500, 7500 + 5625 + 1875}, // 6
369 {1750, 5250, 7000, 7000 + 5250 + 1750}, // 7
370 {1625, 4875, 6500, 6500 + 4875 + 1625}, // 8
371 {1500, 4500, 6000, 6000 + 4500 + 1500}, // 9
372 };
373
374 auto start = std::chrono::system_clock::now();
375 ffrt::qos_interval_begin(it);
376 for (int i = 0; i < frame_num; i++) {
377 int pingpong = i % BUFFER_NUM;
378 // task A
379 ffrt::submit(
__anonbee5675e1402() 380 [i, loop, stalls, &x0, &x1]() {
381 FFRT_LOGI("%u", i);
382 x1[i % BUFFER_NUM] = i;
383 },
__anonbee5675e1502() 384 {x0 + i}, {x1 + pingpong}, ffrt::task_attr().name(("UI" + std::to_string(i)).c_str()));
385 // task B
386 ffrt::submit(
__anonbee5675e1702() 387 [i, loop, stalls, &x1, &x2]() {
388 FFRT_LOGI("%u", i);
389 x2[i % BUFFER_NUM] = i;
390 },
__anonbee5675e1902() 391 {x1 + pingpong}, {x2 + pingpong}, ffrt::task_attr().name(("Render" + std::to_string(i)).c_str()));
392 // task C
393 ffrt::submit(
__anonbee5675e1a02() 394 [i, loop, stalls, &x2, &x3]() {
395 FFRT_LOGI("%u", i);
396 x3[i] = i;
397 },
__anonbee5675e1c02() 398 {x2 + pingpong}, {x3 + i}, ffrt::task_attr().name(("surfaceflinger" + std::to_string(i)).c_str()));
399 }
400 ffrt::wait();
401 ffrt::qos_interval_end(it);
402
403 for (int i = 0; i < frame_num; i++) {
404 EXPECT_EQ(x3[i], i) << "Task C result is incorrect for frame " << i;
405 }
406 }
407
408 ffrt::qos_interval_destroy(it);
409 }
410
AddOne(void * args)411 void AddOne(void* args)
412 {
413 *(static_cast<int*>(args)) += 1;
414 }