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 <cinttypes>
18#include "ffrt_inner.h"
19#include "util.h"
20#include "c/deadline.h"
21#include "c/executor_task.h"
22#include "tm/scpu_task.h"
23#include "dfx/log/ffrt_log_api.h"
24#ifndef WITH_NO_MOCKER
25extern "C" int ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr *attr);
26#endif
27#include "../common.h"
28
29using namespace std;
30using namespace testing;
31#ifdef HWTEST_TESTING_EXT_ENABLE
32using namespace testing::ext;
33#endif
34
35class DependencyTest : public testing::Test {
36protected:
37    static void SetUpTestCase()
38    {
39    }
40
41    static void TearDownTestCase()
42    {
43    }
44
45    virtual void SetUp()
46    {
47    }
48
49    virtual void TearDown()
50    {
51    }
52};
53
54HWTEST_F(DependencyTest, dependency_success_01, TestSize.Level1)
55{
56    int x = 0;
57    ffrt::submit([&]() { x = 2; }, {}, {&x});
58    ffrt::submit([&]() { x = x * 3; }, {&x}, {});
59    ffrt::wait();
60    EXPECT_EQ(x, 6);
61}
62
63HWTEST_F(DependencyTest, update_qos_success_02, TestSize.Level1)
64{
65    int ret = ffrt_task_attr_init(nullptr);
66    EXPECT_EQ(ret, -1);
67    ffrt_task_attr_get_name(nullptr);
68    ffrt_task_attr_set_name(nullptr, "A");
69    ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
70    ffrt_task_attr_get_qos(nullptr);
71    ffrt_task_attr_destroy(nullptr);
72    ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
73    ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
74    ffrt::submit([] {
75        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
76        printf("id is  %" PRIu64 "\n", ffrt::this_task::get_id());
77    });
78    ffrt_this_task_get_id();
79    ffrt::wait();
80    ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_user_initiated));
81#ifndef WITH_NO_MOCKER
82    ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), nullptr);
83#endif
84}
85
86HWTEST_F(DependencyTest, update_qos_success_03, TestSize.Level1)
87{
88    int ret = ffrt_task_attr_init(nullptr);
89    EXPECT_EQ(ret, -1);
90    ffrt::submit([] {
91        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
92    });
93    ffrt_restore_qos_config();
94}
95
96HWTEST_F(DependencyTest, update_qos_success_04, TestSize.Level1)
97{
98    int ret = ffrt_task_attr_init(nullptr);
99    EXPECT_EQ(ret, -1);
100    ffrt::submit([] {
101        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
102    });
103}
104
105HWTEST_F(DependencyTest, update_qos_success_05, TestSize.Level1)
106{
107    int x = 0;
108    int ret = ffrt_task_attr_init(nullptr);
109    EXPECT_EQ(ret, -1);
110    ffrt_task_attr_get_name(nullptr);
111    ffrt_task_attr_set_name(nullptr, "A");
112    ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
113    ffrt_task_attr_get_qos(nullptr);
114    ffrt_task_attr_destroy(nullptr);
115    ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
116    ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
117    ffrt::submit([&] {
118        x++;
119        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
120        printf("id is  %" PRIu64 "\n", ffrt::this_task::get_id());
121    });
122    ffrt_this_task_get_id();
123    ffrt::wait();
124    ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_user_initiated));
125#ifndef WITH_NO_MOCKER
126    ffrt_os_sched_attr attr = {100, 10, 99, 99, 9, "2-3"};
127    ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), &attr);
128#endif
129    EXPECT_EQ(x, 1);
130}
131
132HWTEST_F(DependencyTest, update_qos_failed_01, TestSize.Level1)
133{
134    int x = 0;
135    int ret = ffrt_task_attr_init(nullptr);
136    EXPECT_EQ(ret, -1);
137    ffrt_task_attr_get_name(nullptr);
138    ffrt_task_attr_set_name(nullptr, "A");
139    ffrt_task_attr_set_qos(nullptr, static_cast<int>(ffrt::qos_user_initiated));
140    ffrt_task_attr_get_qos(nullptr);
141    ffrt_task_attr_destroy(nullptr);
142    ffrt_submit_base(nullptr, nullptr, nullptr, nullptr);
143    ffrt_submit_h_base(nullptr, nullptr, nullptr, nullptr);
144    ffrt::submit([&] {
145        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
146        printf("id is  %" PRIu64 "\n", ffrt::this_task::get_id());
147        int ret1 = ffrt_this_task_update_qos(static_cast<int>(ffrt::qos_default));
148        EXPECT_EQ(ret1, 0);
149        x++;
150    });
151    ffrt_this_task_get_id();
152    ffrt::wait();
153#ifndef WITH_NO_MOCKER
154    ffrt_set_cgroup_attr(static_cast<int>(ffrt::qos_user_initiated), nullptr);
155#endif
156    EXPECT_EQ(x, 1);
157}
158
159HWTEST_F(DependencyTest, update_qos_failed_02, TestSize.Level1)
160{
161    int ret = ffrt_task_attr_init(nullptr);
162    EXPECT_EQ(ret, -1);
163    ffrt::submit([] {
164        printf("return %d\n", ffrt::this_task::update_qos(static_cast<int>(ffrt::qos_user_initiated)));
165    });
166}
167
168HWTEST_F(DependencyTest, executor_task_submit_success_01, TestSize.Level1)
169{
170    ffrt_task_attr_t attr;
171    static ffrt_executor_task_t work;
172    work.wq[0] = &work.wq;
173    work.wq[1] = &work.wq;
174    work.type = reinterpret_cast<uintptr_t>(&attr);
175
176    ffrt_executor_task_submit(&work, &attr);
177}
178HWTEST_F(DependencyTest, executor_task_submit_nullptr_01, TestSize.Level1)
179{
180    ffrt_executor_task_submit(nullptr, nullptr);
181}
182
183HWTEST_F(DependencyTest, executor_task_submit_cancel_01, TestSize.Level1)
184{
185    ffrt_executor_task_cancel(nullptr, static_cast<int>(ffrt::qos_user_initiated));
186}
187
188HWTEST_F(DependencyTest, executor_task_submit_cancel_02, TestSize.Level1)
189{
190    ffrt_task_attr_t attr;
191    ffrt_task_attr_init(&attr);
192    ffrt_executor_task_t work;
193    work.type = reinterpret_cast<uintptr_t>(&attr);
194
195    ffrt_task_attr_set_qos(&attr, static_cast<int>(ffrt::qos_user_initiated));
196    ffrt_executor_task_submit(&work, &attr);
197    usleep(10000);
198    int cancelled = ffrt_executor_task_cancel(&work, static_cast<int>(ffrt::qos_user_initiated));
199    EXPECT_EQ(cancelled, 0);
200
201    ffrt_task_attr_destroy(&attr);
202}
203
204HWTEST_F(DependencyTest, update_trace_tag_success_02, TestSize.Level1)
205{
206    ffrt::set_trace_tag("TASK A");
207    ffrt::clear_trace_tag();
208}
209
210HWTEST_F(DependencyTest, task_attr_success_02, TestSize.Level1)
211{
212    ffrt::task_attr tmpTask;
213    tmpTask.name("Task A");
214    tmpTask.qos(static_cast<int>(ffrt::qos_user_initiated));
215    tmpTask.name();
216    tmpTask.qos();
217}
218
219HWTEST_F(DependencyTest, sample_pingpong_pipe_interval_checkpoint, TestSize.Level1)
220{
221    int loops = 5;
222    int frame_num = 2;
223
224    if (getenv("LOOP_NUM")) {
225        loops = atoi(getenv("LOOP_NUM"));
226    }
227    if (getenv("FRAME_NUM")) {
228        frame_num = atoi(getenv("FRAME_NUM"));
229    }
230
231    ffrt::submit([&]() { stall_us(10); }, {}, {});
232
233    auto it = ffrt::qos_interval_create(16, static_cast<int>(ffrt::qos_user_interactive));
234    for (int loop = 0; loop < loops; loop++) {
235        constexpr int FRAME_NUM = 3;
236        constexpr uint32_t BUFFER_NUM = 2;
237        int x0[FRAME_NUM];
238        int x1[BUFFER_NUM];
239        int x2[BUFFER_NUM];
240        int x3[FRAME_NUM];
241
242        int stalls[10][4] = {
243            {2000, 6000, 8000, 8000 + 6000 + 2000}, // 0
244            {2125, 6375, 8500, 8500 + 6375 + 2125}, // 1
245            {2222, 6666, 8888, 8888 + 6666 + 2222}, // 2
246            {2250, 6750, 9000, 9000 + 6750 + 2250}, // 3
247            {2375, 7125, 9500, 9500 + 7125 + 2375}, // 4
248            {2500, 7500, 10000, 10000 + 7500 + 2500}, // 5
249            {1875, 5625, 7500, 7500 + 5625 + 1875}, // 6
250            {1750, 5250, 7000, 7000 + 5250 + 1750}, // 7
251            {1625, 4875, 6500, 6500 + 4875 + 1625}, // 8
252            {1500, 4500, 6000, 6000 + 4500 + 1500}, // 9
253        };
254
255        auto start = std::chrono::system_clock::now();
256        ffrt::qos_interval_begin(it);
257        for (int i = 0; i < frame_num; i++) {
258            int pingpong = i % BUFFER_NUM;
259            // task A
260            ffrt::submit(
261                [i, loop, stalls]() {
262                    FFRT_LOGI("%u", i);
263                },
264                {x0 + i}, {x1 + pingpong}, ffrt::task_attr().name(("UI" + std::to_string(i)).c_str()));
265            // task B
266            ffrt::submit(
267                [i, loop, stalls]() {
268                    FFRT_LOGI("%u", i);
269                },
270                {x1 + pingpong}, {x2 + pingpong}, ffrt::task_attr().name(("Render" + std::to_string(i)).c_str()));
271            // task C
272            ffrt::submit(
273                [i, loop, stalls]() {
274                    FFRT_LOGI("%u", i);
275                },
276                {x2 + pingpong}, {x3 + i}, ffrt::task_attr().name(("surfaceflinger" + std::to_string(i)).c_str()));
277        }
278        ffrt::wait();
279        ffrt::qos_interval_end(it);
280    }
281
282    ffrt::qos_interval_destroy(it);
283}
284