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 }