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 <chrono>
18 #include "ffrt_inner.h"
19 #include "dfx/bbox/bbox.h"
20 #define private public
21 #include "util/worker_monitor.h"
22 #include "sync/poller.h"
23 #undef private
24 #include "c/queue_ext.h"
25 #include "../common.h"
26 #ifdef FFRT_ENABLE_HITRACE_CHAIN
27 #include "dfx/trace/ffrt_trace_chain.h"
28 #endif
29 using namespace ffrt;
30
31 extern void SaveTheBbox();
32 extern void RecordDebugInfo();
33
34 using namespace testing;
35 #ifdef HWTEST_TESTING_EXT_ENABLE
36 using namespace testing::ext;
37 #endif
38
39 class DfxTest : public testing::Test {
40 protected:
SetUpTestCase()41 static void SetUpTestCase()
42 {
43 }
44
TearDownTestCase()45 static void TearDownTestCase()
46 {
47 }
48
SetUp()49 void SetUp() override
50 {
51 }
52
TearDown()53 void TearDown() override
54 {
55 }
56 };
57
58 HWTEST_F(DfxTest, tracetest, TestSize.Level0)
59 {
60 int x = 0;
61 ffrt::submit(
__anon488d7fa30102() 62 [&]() {
63 ffrt::set_trace_tag("task");
64 x++;
65 ffrt::clear_trace_tag();
66 }, {}, {});
67 ffrt::wait();
68 EXPECT_EQ(x, 1);
69 }
70
71 static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
72
SignalHandler(int signo,siginfo_t * info,void * context)73 static void SignalHandler(int signo, siginfo_t* info, void* context __attribute__((unused)))
74 {
75 SaveTheBbox();
76
77 // we need to deregister our signal handler for that signal before continuing.
78 sigaction(signo, &s_oldSa[signo], nullptr);
79 }
80
SignalReg(int signo)81 static void SignalReg(int signo)
82 {
83 sigaction(signo, nullptr, &s_oldSa[signo]);
84 struct sigaction newAction;
85 newAction.sa_flags = SA_RESTART | SA_SIGINFO;
86 newAction.sa_sigaction = SignalHandler;
87 sigaction(signo, &newAction, nullptr);
88 }
89
90 HWTEST_F(DfxTest, queue_dfx_bbox_normal_task_0001, TestSize.Level0)
91 {
92 // 异常信号用例,测试bbox功能正常;
93 int x = 0;
94 ffrt::mutex lock;
95
96 pid_t pid = fork();
97 if (!pid) {
98 printf("pid = %d, thread id= %d start\n", getpid(), pid);
99
__anon488d7fa30402() 100 auto basic1Func = [&]() {
101 std::lock_guard lg(lock);
102 ffrt_usleep(2000);
103 x = x + 1;
104
105 };
106
__anon488d7fa30502() 107 auto basic2Func = [&]() {
108 ffrt_usleep(3000);
109 SignalReg(SIGABRT);
110 raise(SIGABRT); // 向自身进程发送SIGABR
111 };
112
__anon488d7fa30602() 113 auto basic3Func = [&]() {
114 ffrt_usleep(5000);
115 std::lock_guard lg(lock);
116 x = x + 1;
117 };
118
119 for (int i = 0; i < 20; i++) {
120 ffrt::submit(basic1Func, {}, {}, ffrt::task_attr().qos(static_cast<int>(ffrt::qos_default)));
121 }
122 for (int i = 0; i < 10; i++) {
123 ffrt::submit(basic3Func, {}, {}, ffrt::task_attr().qos(static_cast<int>(ffrt::qos_default)));
124 }
125 auto task = ffrt::submit_h(basic2Func, {}, {}, ffrt::task_attr().qos(static_cast<int>(ffrt::qos_background)));
126
127 ffrt::wait({task});
128 printf("pid = %d, thread id= %d end\n", getpid(), pid);
129 exit(0);
130 }
131 sleep(1);
132 }
133
134 HWTEST_F(DfxTest, queue_dfx_bbox_queue_task_0001, TestSize.Level0)
135 {
136 // 异常信号用例,测试bbox功能正常;
137 int x = 0;
138 ffrt::mutex lock;
139
140 pid_t pid = fork();
141 if (!pid) {
142 printf("pid = %d, thread id= %d start\n", getpid(), pid);
143 ffrt_queue_attr_t queue_attr;
144 ffrt_queue_attr_t queue_attr2;
145 (void)ffrt_queue_attr_init(&queue_attr); // 初始化属性,必须
146 ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
147 (void)ffrt_queue_attr_init(&queue_attr2); // 初始化属性,必须
148 ffrt_queue_t queue_handle2 = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr2);
__anon488d7fa30702() 149 std::function<void()> basic1Func = [&]() {
150 lock.lock();
151 ffrt_usleep(5000);
152 x = x + 1;
153 lock.unlock();
154 };
155
__anon488d7fa30802() 156 auto basic3Func = [&]() {
157 lock.lock();
158 sleep(2);
159 lock.unlock();
160 };
161
162 auto task = ffrt::submit_h(basic3Func, {}, {}, ffrt::task_attr().qos(static_cast<int>(ffrt::qos_background)));
163 ffrt_queue_submit(queue_handle, create_function_wrapper(basic1Func, ffrt_function_kind_queue), nullptr);
164 ffrt_queue_submit(queue_handle2, create_function_wrapper(basic1Func, ffrt_function_kind_queue), nullptr);
165
166 SaveTheBbox();
167 ffrt::wait({task});
168 ffrt_queue_attr_destroy(&queue_attr);
169 ffrt_queue_destroy(queue_handle);
170 ffrt_queue_attr_destroy(&queue_attr2);
171 ffrt_queue_destroy(queue_handle2);
172 printf("pid = %d, thread id= %d end\n", getpid(), pid);
173 exit(0);
174 }
175 sleep(1);
176 }
177
178 /*
179 * 测试用例名称:dfx_bbox_normal_task_0002
180 * 测试用例描述:提交有依赖关系的任务,测试SaveTheBbox和RecordDebugInfo函数
181 * 预置条件 :无
182 * 操作步骤 :提交嵌套任务,子任务等待cv和数据依赖,调用SaveTheBbox和RecordDebugInfo接口
183 * 预期结果 :SaveTheBbox()函数正确执行
184 */
185 HWTEST_F(DfxTest, dfx_bbox_normal_task_0002, TestSize.Level0)
186 {
187 SaveTheBbox();
__anon488d7fa30902() 188 ffrt::submit([]() {
189 RecordDebugInfo();
190 });
191 ffrt::wait();
192 }
193
stall_us_impl(size_t us)194 static inline void stall_us_impl(size_t us)
195 {
196 auto start = std::chrono::system_clock::now();
197 size_t passed = 0;
198 while (passed < us) {
199 passed = std::chrono::duration_cast<std::chrono::microseconds>(
200 std::chrono::system_clock::now() - start).count();
201 }
202 }
203
stall_us(size_t us)204 void stall_us(size_t us)
205 {
206 stall_us_impl(us);
207 }
208
209 /*
210 * 测试用例名称:normaltsk_timeout_executing
211 * 测试用例描述:并发任务WorkerMonitor检测到任务执行超时
212 * 操作步骤 :1、提交执行时间长任务
213 * 预期结果 :成功触发任务执行超时告警
214 */
215 HWTEST_F(DfxTest, normaltsk_timeout_executing, TestSize.Level1)
216 {
217 ffrt::WorkerMonitor::GetInstance().timeoutUs_ = 1000000;
218 ffrt::WorkerMonitor::GetInstance().SubmitTaskMonitor(1000000);
219 ffrt_task_timeout_set_threshold(1000);
220 int x = 0;
221 auto h = ffrt::submit_h(
__anon488d7fa30a02() 222 [&]() {
223 stall_us(3000000);
224 x++;
225 }, {}, {});
226 ffrt::wait({h});
227 EXPECT_EQ(x, 1);
228 }
229
230 /*
231 * 测试用例名称:normaltsk_timeout_pending
232 * 测试用例描述:并发任务WorkerMonitor检测到任务调度超时
233 * 操作步骤 :1、限制worker数为1
234 2、提交1个执行时间长任务占住worker,1个即时任务等待
235 * 预期结果 :触发PENDING超时告警
236 */
237 HWTEST_F(DfxTest, normaltsk_timeout_pending, TestSize.Level1)
238 {
239 ffrt_task_timeout_set_threshold(1000);
240 ffrt_set_cpu_worker_max_num(qos_default, 2);
241 constexpr int numTasks = 3;
242 std::atomic<int> x = 0;
243
244 for (int i = 0; i < numTasks; i++) {
245 ffrt::submit(
__anon488d7fa30d02() 246 [&]() {
247 stall_us(2000000);
248 x.fetch_add(1, std::memory_order_relaxed);
249 }, {}, {});
250 }
251 ffrt::wait();
252 EXPECT_EQ(x, numTasks);
253 }
254
255 /*
256 * 测试用例名称:normaltsk_timeout_multi
257 * 测试用例描述:多个并发任务WorkerMonitor检测超时
258 * 操作步骤 :1、提交多个执行时间长任务
259 * 预期结果 :正确触发多次超时告警
260 */
261 HWTEST_F(DfxTest, normaltsk_timeout_multi, TestSize.Level1)
262 {
263 ffrt_task_timeout_set_threshold(1000);
264 constexpr int numTasks = 5;
265 std::atomic<int> x = 0;
266 for (int i = 0; i < numTasks; i++) {
267 ffrt::submit(
__anon488d7fa31002() 268 [&]() {
269 stall_us(1500000);
270 x.fetch_add(1, std::memory_order_relaxed);
271 }, {}, {});
272 }
273 ffrt::wait();
274 EXPECT_EQ(x, numTasks);
275 }
276
277 /*
278 * 测试用例名称:normaltsk_timeout_delay
279 * 测试用例描述:并发任务WorkerMonitor不检测延时任务的主动延时
280 * 操作步骤 :1、提交延时任务
281 * 预期结果 :主动延时期间不触发超时告警,但任务执行期间触发
282 */
283 HWTEST_F(DfxTest, normaltsk_timeout_delay, TestSize.Level1)
284 {
285 ffrt_task_timeout_set_threshold(1000);
286 constexpr int numTasks = 2;
287 std::atomic<int> x = 0;
288 for (int i = 0; i < numTasks; i++) {
__anon488d7fa31302() 289 ffrt::submit([&]() {
290 std::cout << "delay " << 1500 << " us\n";
291 x.fetch_add(1, std::memory_order_relaxed);
292 stall_us(1500000);
293 }, {}, {}, ffrt::task_attr().delay(1500000));
294 }
295 ffrt::wait();
296 EXPECT_EQ(x, numTasks);
297 ffrt::WorkerMonitor::GetInstance().timeoutUs_ = 30000000;
298 }
299
MyCallback1(uint64_t id,const char * message,uint32_t length)300 void MyCallback1(uint64_t id, const char* message, uint32_t length)
301 {
302 FFRT_LOGE("call ffrt_queue_monitor timeout_callback");
303 }
304
Testfun(void * data)305 static void Testfun(void* data)
306 {
307 int* testData = static_cast<int*>(data);
308 *testData += 1;
309 printf("%d, timeout callback\n", *testData);
310 }
311 static void (*g_cb)(void*) = Testfun;
312
313 HWTEST_F(DfxTest, hitrace_test_normal, TestSize.Level0)
314 {
315 #ifdef FFRT_ENABLE_HITRACE_CHAIN
316 int HITRACE_FLAG_INCLUDE_ASYNC = 1 << 0;
317 const HiTraceIdStruct traceId = TraceChainAdapter::Instance().HiTraceChainBegin("ffrt_dfx_test",
318 HITRACE_FLAG_INCLUDE_ASYNC);
319 ffrt_task_timeout_set_cb(MyCallback1);
320 ffrt_task_timeout_set_threshold(1000);
321 FFRT_LOGE("hitrace_test begin");
322 std::atomic<std::uint64_t> x{0};
323 for (int i = 0; i < 5; i++) {
324 ffrt::submit(
__anon488d7fa31602() 325 [&]() {
326 stall_us(500000);
327 x.fetch_add(1);
328 }, {}, {});
329 }
330 ffrt::wait();
331
332 queue* testQueue = new queue("test_queue");
__anon488d7fa31902null333 auto t = testQueue->submit_h([] { stall_us(1100000); FFRT_LOGE("done");}, {});
334 testQueue->wait(t);
335 FFRT_LOGE("hitrace_test end");
336 TraceChainAdapter::Instance().HiTraceChainEnd(&traceId);
337 EXPECT_EQ(x, 5);
338 delete testQueue;
339 #endif
340 }
341
342 HWTEST_F(DfxTest, hitrace_test_poller, TestSize.Level0)
343 {
344 #ifdef FFRT_ENABLE_HITRACE_CHAIN
345 int HITRACE_FLAG_INCLUDE_ASYNC = 1 << 0;
346 const HiTraceIdStruct traceId = TraceChainAdapter::Instance().HiTraceChainBegin("ffrt_dfx_test",
347 HITRACE_FLAG_INCLUDE_ASYNC);
348 Poller poller;
349 // 1.组装timeMap_
350 static int result0 = 0;
351 int* xf = &result0;
352 void* data = xf;
353 uint64_t timeout = 10;
354 uint64_t timeout1 = 11;
355 uint64_t timeout2 = 12;
356 uint64_t sleepTime = 25000;
357 poller.RegisterTimer(timeout, data, g_cb, false);
358 poller.RegisterTimer(timeout1, data, g_cb, false);
359 poller.RegisterTimer(timeout2, data, g_cb, false);
360 // 调用PollOnce,预计timerMap_为空,全部清除
361 usleep(sleepTime);
362 poller.PollOnce(1);
363 EXPECT_EQ(true, poller.DetermineEmptyMap());
364
365 uint64_t timeout3 = 10000;
366 uint64_t timeout4 = 100;
367 int loopNum = 2;
368 poller.RegisterTimer(timeout3, data, g_cb, false);
369 TimePoint start = std::chrono::steady_clock::now();
370 for (int i = 0; i < loopNum; ++i) {
371 poller.PollOnce(timeout4);
372 }
373 TimePoint end = std::chrono::steady_clock::now();
374 int m = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
375 // 预计等待时间为100,可能有几毫秒的误差
376 EXPECT_EQ(true, m >= timeout4 && m < timeout3);
377 TraceChainAdapter::Instance().HiTraceChainEnd(&traceId);
378 #endif
379 }
380