• 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 <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 }