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