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 <random>
17 #include <csignal>
18 #include <gtest/gtest.h>
19 #include "core/entity.h"
20 #include "core/version_ctx.h"
21 #include "ffrt_inner.h"
22 #include "c/ffrt_ipc.h"
23 #include "sched/task_state.h"
24 #include "dfx/log/ffrt_log_api.h"
25 #include "dfx/bbox/bbox.h"
26 #include "tm/cpu_task.h"
27 #include "tm/queue_task.h"
28 #include "tm/scpu_task.h"
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 using namespace ffrt;
37 
38 class CoreTest : public testing::Test {
39 protected:
SetUpTestCase()40     static void SetUpTestCase()
41     {
42     }
43 
TearDownTestCase()44     static void TearDownTestCase()
45     {
46     }
47 
SetUp()48     virtual void SetUp()
49     {
50     }
51 
TearDown()52     virtual void TearDown()
53     {
54     }
55 };
56 
HWTEST_F(CoreTest, core_test_success_01, TestSize.Level1)57 HWTEST_F(CoreTest, core_test_success_01, TestSize.Level1)
58 {
59     sync_io(0);
60 }
61 
HWTEST_F(CoreTest, task_ctx_success_01, TestSize.Level1)62 HWTEST_F(CoreTest, task_ctx_success_01, TestSize.Level1)
63 {
64     auto func1 = ([]() {std::cout << std::endl << " push a task " << std::endl;});
65     SCPUEUTask *task1 = new SCPUEUTask(nullptr, nullptr, 0, QoS(static_cast<int>(qos_user_interactive)));
66     auto func2 = ([]() {std::cout << std::endl << " push a task " << std::endl;});
67     SCPUEUTask *task2 = new SCPUEUTask(nullptr, task1, 0, QoS());
68     QoS qos = QoS(static_cast<int>(qos_inherit));
69     task2->SetQos(qos);
70     EXPECT_EQ(task2->qos, static_cast<int>(qos_user_interactive));
71     delete task1;
72     delete task2;
73 }
74 
HWTEST_F(CoreTest, ffrt_submit_wait_success_01, TestSize.Level1)75 HWTEST_F(CoreTest, ffrt_submit_wait_success_01, TestSize.Level1)
76 {
77     const uint32_t sleepTime = 3 * 200;
78     int x = 0;
79     ffrt_task_attr_t* attr = (ffrt_task_attr_t *) malloc(sizeof(ffrt_task_attr_t));
80     ffrt_task_attr_init(attr);
81     std::function<void()>&& basicFunc = [&]() {
82         EXPECT_EQ(x, 0);
83         usleep(sleepTime);
84         x = x + 1;
85     };
86     ffrt_function_header_t* basicFunc_ht = ffrt::create_function_wrapper((basicFunc));
87     const std::vector<ffrt_dependence_t> in_deps = {};
88     ffrt_deps_t in{static_cast<uint32_t>(in_deps.size()), in_deps.data()};
89     const std::vector<ffrt_dependence_t> ou_deps = {};
90     ffrt_deps_t ou{static_cast<uint32_t>(ou_deps.size()), ou_deps.data()};
91     const std::vector<ffrt_dependence_t> wait_deps = {};
92     ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
93     const ffrt_deps_t *wait_null = nullptr;
94     ffrt_submit_base(basicFunc_ht, &in, &ou, attr);
95     EXPECT_EQ(x, 0);
96     ffrt_wait_deps(wait_null);
97     EXPECT_EQ(x, 0);
98     ffrt_wait_deps(&wait);
99     EXPECT_EQ(x, 0);
100     ffrt_wait();
101     EXPECT_EQ(x, 1);
102     ffrt_task_attr_destroy(attr);
103     free(attr);
104     attr = nullptr;
105 }
106 
107 /**
108  * @tc.name: ThreadWaitAndNotifyModeCheck
109  * @tc.desc: Test function of ThreadWaitMode and ThreadNotifyMode
110  * @tc.type: FUNC
111  */
HWTEST_F(CoreTest, ThreadWaitAndNotifyMode, TestSize.Level1)112 HWTEST_F(CoreTest, ThreadWaitAndNotifyMode, TestSize.Level1)
113 {
114     SCPUEUTask* task = new SCPUEUTask(nullptr, nullptr, 0, QoS());
115 
116     // when executing task is nullptr
117     EXPECT_EQ(ThreadWaitMode(nullptr), true);
118 
119     // when executing task is root
120     EXPECT_EQ(ThreadWaitMode(task), true);
121 
122     // when executing task in legacy mode
123     SCPUEUTask* parent = new SCPUEUTask(nullptr, nullptr, 0, QoS());
124     task->parent = parent;
125     task->legacyCountNum = 1;
126     EXPECT_EQ(ThreadWaitMode(task), true);
127 
128     // when task is valid and not in legacy mode
129     task->legacyCountNum = 0;
130     EXPECT_EQ(ThreadWaitMode(task), false);
131 
132     // when block thread is false
133     EXPECT_EQ(ThreadNotifyMode(task), false);
134 
135     // when block thread is true
136     task->blockType = BlockType::BLOCK_THREAD;
137     EXPECT_EQ(ThreadNotifyMode(task), true);
138 
139     delete parent;
140     delete task;
141 }
142 
143 /**
144  * @tc.name: ffrt_this_task_set_legacy_mode_yeild_test
145  * @tc.desc: Test function of ffrt_this_task_set_legacy_mode with ffrt_yield
146  * @tc.type: FUNC
147  */
HWTEST_F(CoreTest, ffrt_this_task_set_legacy_mode_yield_test, TestSize.Level1)148 HWTEST_F(CoreTest, ffrt_this_task_set_legacy_mode_yield_test, TestSize.Level1)
149 {
150     int count = 12;
151     for (int i = 0; i < count; i++) {
152         ffrt::submit(
153             [&]() {
154             ffrt_this_task_set_legacy_mode(true);
155             ffrt_usleep(100);
156             printf("test");
157             ffrt_yield();
158             ffrt_this_task_set_legacy_mode(false);
159         },
160             {}, {});
161     }
162     ffrt::wait();
163 }
164 
165 /**
166  * 测试用例名称:task_attr_set_timeout
167  * 测试用例描述:验证task_attr的设置timeout接口
168  * 预置条件:创建有效的task_attr
169  * 操作步骤:设置timeout值,通过get接口与设置值对比
170  * 预期结果:设置成功
171  */
HWTEST_F(CoreTest, task_attr_set_timeout, TestSize.Level1)172 HWTEST_F(CoreTest, task_attr_set_timeout, TestSize.Level1)
173 {
174     ffrt_task_attr_t* attr = (ffrt_task_attr_t *) malloc(sizeof(ffrt_task_attr_t));
175     ffrt_task_attr_init(attr);
176     ffrt_task_attr_set_timeout(attr, 1000);
177     uint64_t timeout = ffrt_task_attr_get_timeout(attr);
178     EXPECT_EQ(timeout, 1000);
179 }
180 
181 /**
182  * 测试用例名称:task_attr_set_timeout_nullptr
183  * 测试用例描述:验证task_attr的设置timeout接口的异常场景
184  * 预置条件:针对nullptr进行设置
185  * 操作步骤:设置timeout值,通过get接口与设置值对比
186  * 预期结果:设置失败,返回值为0
187  */
HWTEST_F(CoreTest, task_attr_set_timeout_nullptr, TestSize.Level1)188 HWTEST_F(CoreTest, task_attr_set_timeout_nullptr, TestSize.Level1)
189 {
190     ffrt_task_attr_t* attr = nullptr;
191     ffrt_task_attr_set_timeout(attr, 1000);
192     uint64_t timeout = ffrt_task_attr_get_timeout(attr);
193     EXPECT_EQ(timeout, 0);
194 }
195 
196 /**
197  * 测试用例名称:ffrt_task_handle_ref_nullptr
198  * 测试用例描述:验证task_handle的增加、消减引用计数接口的异常场景
199  * 预置条件:针对nullptr进行设置
200  * 操作步骤:对nullptr进行调用
201  * 预期结果:接口校验异常场景成功,用例正常执行结束
202  */
HWTEST_F(CoreTest, ffrt_task_handle_ref_nullptr, TestSize.Level1)203 HWTEST_F(CoreTest, ffrt_task_handle_ref_nullptr, TestSize.Level1)
204 {
205     ffrt_task_handle_inc_ref(nullptr);
206     ffrt_task_handle_dec_ref(nullptr);
207 }
208 
209 /**
210  * 测试用例名称:ffrt_task_handle_ref
211  * 测试用例描述:验证task_handle的增加、消减引用计数接口
212  * 预置条件:创建有效的task_handle
213  * 操作步骤:对task_handle进行设置引用计数接口
214  * 预期结果:读取rc值
215  */
HWTEST_F(CoreTest, ffrt_task_handle_ref, TestSize.Level1)216 HWTEST_F(CoreTest, ffrt_task_handle_ref, TestSize.Level1)
217 {
218     // 验证notify_worker的功能
219     int result = 0;
220     ffrt_task_attr_t taskAttr;
221     (void)ffrt_task_attr_init(&taskAttr); // 初始化task属性,必须
222     ffrt_task_attr_set_delay(&taskAttr, 10000); // 延时10ms执行
223     std::function<void()>&& OnePlusFunc = [&result]() { result += 1; };
224     ffrt_task_handle_t handle = ffrt_submit_h_base(ffrt::create_function_wrapper(OnePlusFunc), {}, {}, &taskAttr);
225     auto task = static_cast<ffrt::CPUEUTask*>(handle);
226     EXPECT_EQ(task->rc.load(), 2); // task还未执行完成,所以task和handle各计数一次
227     ffrt_task_handle_inc_ref(handle);
228     EXPECT_EQ(task->rc.load(), 3);
229     ffrt_task_handle_dec_ref(handle);
230     EXPECT_EQ(task->rc.load(), 2);
231     ffrt::wait({handle});
232     EXPECT_EQ(result, 1);
233     ffrt_task_handle_destroy(handle);
234 }
235 
236 /**
237  * 测试用例名称:WaitFailWhenReuseHandle
238  * 测试用例描述:构造2个submit_h的任务,验证task_handle转成dependence后,调用ffrt::wait的场景
239  * 预置条件:创建一个submit_h任务,确保执行完成,且将task_handle转成dependence后保存
240  * 操作步骤:创建另外一个task_handle任务,并且先执行ffrt::wait保存的dependence的数组
241  * 预期结果:任务正常执行结束
242  */
HWTEST_F(CoreTest, WaitFailWhenReuseHandle, TestSize.Level1)243 HWTEST_F(CoreTest, WaitFailWhenReuseHandle, TestSize.Level1)
244 {
245     std::vector<ffrt::dependence> deps;
246     {
247         auto h = ffrt::submit_h([] { printf("task0 done\n"); });
248         printf("task0 handle: %p\n:", static_cast<void*>(h));
249         deps.emplace_back(h);
250     }
251     usleep(1000);
252     std::atomic_bool stop = false;
253     auto h = ffrt::submit_h([&] {
254         printf("task1 start\n");
255         while (!stop);
256         printf("task1 done\n");
257         });
258     ffrt::wait(deps);
259     stop = true;
260     ffrt::wait();
261 }
262 
263 /*
264  * 测试用例名称:ffrt_task_get_tid_test
265  * 测试用例描述:测试ffrt_task_get_tid接口
266  * 预置条件    :创建SCPUEUTask
267  * 操作步骤    :调用ffrt_task_get_tid方法,入参分别为SCPUEUTask、QueueTask对象和空指针
268  * 预期结果    :ffrt_task_get_tid功能正常,传入空指针时返回0
269  */
HWTEST_F(CoreTest, ffrt_task_get_tid_test, TestSize.Level1)270 HWTEST_F(CoreTest, ffrt_task_get_tid_test, TestSize.Level1)
271 {
272     ffrt::CPUEUTask* task = new ffrt::SCPUEUTask(nullptr, nullptr, 0, ffrt::QoS(2));
273     ffrt::QueueTask* queueTask = new ffrt::QueueTask(nullptr);
274     pthread_t tid = ffrt_task_get_tid(task);
275     EXPECT_EQ(tid, 0);
276 
277     tid = ffrt_task_get_tid(queueTask);
278     EXPECT_EQ(tid, 0);
279 
280     tid = ffrt_task_get_tid(nullptr);
281     EXPECT_EQ(tid, 0);
282 
283     delete task;
284     delete queueTask;
285 }
286 
287 /*
288 * 测试用例名称:ffrt_get_cur_cached_task_id_test
289 * 测试用例描述:测试ffrt_get_cur_cached_task_id接口
290 * 预置条件    :设置ExecuteCtx::Cur->lastGid_为自定义值
291 * 操作步骤    :调用ffrt_get_cur_cached_task_id接口
292 * 预期结果    :ffrt_get_cur_cached_task_id返回值与自定义值相同
293 */
HWTEST_F(CoreTest, ffrt_get_cur_cached_task_id_test, TestSize.Level1)294 HWTEST_F(CoreTest, ffrt_get_cur_cached_task_id_test, TestSize.Level1)
295 {
296     auto ctx = ffrt::ExecuteCtx::Cur();
297     ctx->lastGid_ = 15;
298     EXPECT_EQ(ffrt_get_cur_cached_task_id(), 15);
299 
300     ffrt::submit([] {});
301     ffrt::wait();
302 
303     EXPECT_NE(ffrt_get_cur_cached_task_id(), 0);
304 }