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 #include <array>
16 #include <gtest/gtest.h>
17 #include <regex>
18 #include <thread>
19 #include "c/ffrt_dump.h"
20 #include "dfx/log/ffrt_log_api.h"
21 #include "ffrt_inner.h"
22 #include "securec.h"
23 #include "util.h"
24 #include "../common.h"
25 
26 static const int BUFFER_SIZE = 120000;
27 static const int SLEEP_MS = 3 * 1000;
28 static const int TASK_NUM_9 = 9;
29 static const int TASK_NUM_10 = 10;
30 static const int TASK_NUM_29 = 29;
31 static const int TASK_NUM_40 = 40;
32 static const int TASK_NUM_600 = 600;
33 static const int TASK_NUM_610 = 610;
34 
35 using namespace std;
36 using namespace ffrt;
37 using namespace testing;
38 #ifdef HWTEST_TESTING_EXT_ENABLE
39 using namespace testing::ext;
40 #endif
41 
42 class QueueDumpTest : public testing::Test {
43 protected:
SetUpTestCase()44     static void SetUpTestCase()
45     {
46     }
47 
TearDownTestCase()48     static void TearDownTestCase()
49     {
50     }
51 
SetUp()52     virtual void SetUp()
53     {
54     }
55 
TearDown()56     virtual void TearDown()
57     {
58     }
59 };
60 
61 int g_cnt = 0;
62 std::function<void()>&& basicFunc = []() { g_cnt += 1; };
63 std::function<void()>&& sleepFunc = []() { std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); };
64 
QueueDumpTask1Test(ffrt_queue_t& queue_handle, char* buf)65 static void QueueDumpTask1Test(ffrt_queue_t& queue_handle, char* buf)
66 {
67     ffrt_task_attr_t task_attr;
68     (void)ffrt_task_attr_init(&task_attr);
69     ffrt_task_attr_set_name(&task_attr, "task1");
70     for (int i = 0; i < TASK_NUM_9; ++i) {
71         ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
72     }
73     ffrt_task_handle_t t =
74         ffrt_queue_submit_h(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
75     ffrt_queue_wait(t);
76     EXPECT_EQ(g_cnt, TASK_NUM_10);
77     // dump队列信息
78     int ret = ffrt_queue_dump(queue_handle, "eventHandler1", buf, BUFFER_SIZE, true);
79     EXPECT_TRUE(ret > 0);
80     // 预期dump信息:
81     // 1.tag为eventHandler1
82     // 2.当前执行任务名称为task1
83     // 3.有10条历史执行的任务,且任务名称都是task1
84     // 4.无剩余未执行的任务
85     std::string str(buf);
86     std::regex pattern(R"(eventHandler1 Current Running: start at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task1.*) \}
87 eventHandler1 History event queue information:
88 (eventHandler1 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), trigger time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), complete time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task1.*) \}
89 ){10}eventHandler1 Immediate priority event queue information:
90 eventHandler1 Total size of Immediate events : 0
91 eventHandler1 High priority event queue information:
92 eventHandler1 Total size of High events : 0
93 eventHandler1 Low priority event queue information:
94 eventHandler1 Total size of Low events : 0
95 eventHandler1 Idle priority event queue information:
96 eventHandler1 Total size of Idle events : 0
97 eventHandler1 Vip priority event queue information:
98 eventHandler1 Total size of Vip events : 0
99 eventHandler1 Total event size : 0
100 )");
101     EXPECT_TRUE(std::regex_match(str, pattern));
102     ffrt_task_handle_destroy(t);
103     ffrt_task_attr_destroy(&task_attr);
104 }
105 
QueueDumpTask2Test(ffrt_queue_t& queue_handle, char* buf)106 static void QueueDumpTask2Test(ffrt_queue_t& queue_handle, char* buf)
107 {
108     ffrt_task_attr_t task_attr;
109     (void)ffrt_task_attr_init(&task_attr);
110     ffrt_task_attr_set_name(&task_attr, "task2");
111     for (int i = 0; i < TASK_NUM_29; ++i) {
112         ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
113     }
114     ffrt_task_handle_t t =
115         ffrt_queue_submit_h(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
116     ffrt_queue_wait(t);
117     EXPECT_EQ(g_cnt, TASK_NUM_40);
118     // dump队列信息
119     memset_s(buf, sizeof(char) * BUFFER_SIZE, 0, sizeof(char) * BUFFER_SIZE);
120     int ret = ffrt_queue_dump(queue_handle, "eventHandler2", buf, BUFFER_SIZE, true);
121     EXPECT_TRUE(ret > 0);
122     // 预期dump信息:
123     // 1.tag为eventHandler2
124     // 2.当前执行任务名称为task2
125     // 3.有32条历史执行的任务
126     // 4.无剩余未执行的任务
127     std::string str(buf);
128     std::regex pattern(R"(eventHandler2 Current Running: start at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task2.*) \}
129 eventHandler2 History event queue information:
130 (eventHandler2 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), trigger time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), complete time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = ([^\}]*?) \}
131 ){32}eventHandler2 Immediate priority event queue information:
132 eventHandler2 Total size of Immediate events : 0
133 eventHandler2 High priority event queue information:
134 eventHandler2 Total size of High events : 0
135 eventHandler2 Low priority event queue information:
136 eventHandler2 Total size of Low events : 0
137 eventHandler2 Idle priority event queue information:
138 eventHandler2 Total size of Idle events : 0
139 eventHandler2 Vip priority event queue information:
140 eventHandler2 Total size of Vip events : 0
141 eventHandler2 Total event size : 0
142 )");
143     EXPECT_TRUE(std::regex_match(str, pattern));
144     ffrt_task_handle_destroy(t);
145     ffrt_task_attr_destroy(&task_attr);
146 }
147 
QueueDumpTask3Test(ffrt_queue_t& queue_handle, char* buf)148 static void QueueDumpTask3Test(ffrt_queue_t& queue_handle, char* buf)
149 {
150     ffrt_task_attr_t task_attr;
151     (void)ffrt_task_attr_init(&task_attr);
152     ffrt_task_attr_set_name(&task_attr, "task3");
153     ffrt_queue_submit(queue_handle, create_function_wrapper(sleepFunc, ffrt_function_kind_queue), &task_attr);
154     // dump队列信息
155     memset_s(buf, sizeof(char) * BUFFER_SIZE, 0, sizeof(char) * BUFFER_SIZE);
156     int ret = ffrt_queue_dump(queue_handle, "eventHandler3", buf, BUFFER_SIZE, true);
157     EXPECT_TRUE(ret > 0);
158     // 预期dump信息:
159     // 1.tag为eventHandler3
160     // 2.当前执行任务名称为task3
161     // 3.有32条历史执行的任务
162     // 4.无剩余未执行的任务
163     std::string str(buf);
164     std::regex pattern(R"(eventHandler3 Current Running: start at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task3.*) \}
165 eventHandler3 History event queue information:
166 (eventHandler3 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), trigger time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), complete time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = ([^\}]*?) \}
167 ){32}eventHandler3 Immediate priority event queue information:
168 eventHandler3 Total size of Immediate events : 0
169 eventHandler3 High priority event queue information:
170 eventHandler3 Total size of High events : 0
171 eventHandler3 Low priority event queue information:
172 eventHandler3 Total size of Low events : 0
173 eventHandler3 Idle priority event queue information:
174 eventHandler3 Total size of Idle events : 0
175 eventHandler3 Vip priority event queue information:
176 eventHandler3 Total size of Vip events : 0
177 eventHandler3 Total event size : 0
178 )");
179     EXPECT_TRUE(std::regex_match(str, pattern));
180     ffrt_task_attr_destroy(&task_attr);
181 }
182 
QueueDumpPriorityTest(ffrt_queue_t& queue_handle, ffrt_task_attr_t& task_attr, ffrt_inner_queue_priority_t priority, const char* name)183 static void QueueDumpPriorityTest(ffrt_queue_t& queue_handle, ffrt_task_attr_t& task_attr,
184     ffrt_inner_queue_priority_t priority, const char* name)
185 {
186     (void)ffrt_task_attr_init(&task_attr);
187     ffrt_task_attr_set_queue_priority(&task_attr, static_cast<ffrt_queue_priority_t>(priority));
188     ffrt_task_attr_set_name(&task_attr, name);
189     for (int i = 0; i < TASK_NUM_10; ++i) {
190         ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
191     }
192 }
193 
QueueDumpPriorityTest(ffrt_queue_t& queue_handle, char* buf)194 static void QueueDumpPriorityTest(ffrt_queue_t& queue_handle, char* buf)
195 {
196     ffrt_task_attr_t task_attr4;
197     QueueDumpPriorityTest(queue_handle, task_attr4, ffrt_inner_queue_priority_immediate, "task4");
198     ffrt_task_attr_t task_attr5;
199     QueueDumpPriorityTest(queue_handle, task_attr5, ffrt_inner_queue_priority_high, "task5");
200     ffrt_task_attr_t task_attr6;
201     QueueDumpPriorityTest(queue_handle, task_attr6, ffrt_inner_queue_priority_low, "task6");
202     ffrt_task_attr_t task_attr7;
203     QueueDumpPriorityTest(queue_handle, task_attr7, ffrt_inner_queue_priority_idle, "task7");
204     ffrt_task_attr_t task_attr8;
205     QueueDumpPriorityTest(queue_handle, task_attr8, ffrt_inner_queue_priority_vip, "task8");
206     memset_s(buf, sizeof(char) * BUFFER_SIZE, 0, sizeof(char) * BUFFER_SIZE);
207     int ret = ffrt_queue_dump(queue_handle, "eventHandler4", buf, BUFFER_SIZE, true);
208     EXPECT_TRUE(ret > 0);
209     // 预期dump信息:
210     // 1.tag为eventHandler4
211     // 2.当前执行任务名称为task3
212     // 3.有32条历史执行的任务
213     // 4.5种优先级各有10条任务
214     std::string str(buf);
215     std::regex pattern(R"(eventHandler4 Current Running: start at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task3.*) \}
216 eventHandler4 History event queue information:
217 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), trigger time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), complete time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = ([^\}]*?) \}
218 ){32}eventHandler4 Immediate priority event queue information:
219 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task4.*) \}
220 ){10}eventHandler4 Total size of Immediate events : 10
221 eventHandler4 High priority event queue information:
222 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task5.*) \}
223 ){10}eventHandler4 Total size of High events : 10
224 eventHandler4 Low priority event queue information:
225 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task6.*) \}
226 ){10}eventHandler4 Total size of Low events : 10
227 eventHandler4 Idle priority event queue information:
228 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task7.*) \}
229 ){10}eventHandler4 Total size of Idle events : 10
230 eventHandler4 Vip priority event queue information:
231 (eventHandler4 No. (\d+) : Event \{ send thread = (\d+), send time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), handle time = (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}), task name = (.*task8.*) \}
232 ){10}eventHandler4 Total size of Vip events : 10
233 eventHandler4 Total event size : 50
234 )");
235     EXPECT_TRUE(std::regex_match(str, pattern));
236     ffrt_task_attr_destroy(&task_attr4);
237     ffrt_task_attr_destroy(&task_attr5);
238     ffrt_task_attr_destroy(&task_attr6);
239     ffrt_task_attr_destroy(&task_attr7);
240     ffrt_task_attr_destroy(&task_attr8);
241 }
242 
QueueDumpMaxDumpSizeTest(ffrt_queue_t& queue_handle, char* buf)243 static void QueueDumpMaxDumpSizeTest(ffrt_queue_t& queue_handle, char* buf)
244 {
245     ffrt_task_attr_t task_attr;
246     (void)ffrt_task_attr_init(&task_attr);
247     ffrt_task_attr_set_queue_priority(&task_attr, static_cast<ffrt_queue_priority_t>(ffrt_inner_queue_priority_high));
248     ffrt_task_attr_set_name(&task_attr, "task9");
249     for (int i = 0; i < TASK_NUM_600; ++i) {
250         ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc, ffrt_function_kind_queue), &task_attr);
251     }
252     // dump队列信息
253     memset_s(buf, sizeof(char) * BUFFER_SIZE, 0, sizeof(char) * BUFFER_SIZE);
254     int ret = ffrt_queue_dump(queue_handle, "eventHandler9", buf, BUFFER_SIZE, false);
255     EXPECT_TRUE(ret > 0);
256     ffrt_task_attr_destroy(&task_attr);
257 }
258 
259 /**
260  * @brief queue dump interface user cases
261  */
HWTEST_F(QueueDumpTest, queue_dump_case, TestSize.Level1)262 HWTEST_F(QueueDumpTest, queue_dump_case, TestSize.Level1)
263 {
264     // 创建类型为ffrt_queue_eventhandler_adapter的队列
265     ffrt_queue_attr_t queue_attr;
266     (void)ffrt_queue_attr_init(&queue_attr);
267     ffrt_queue_attr_set_max_concurrency(&queue_attr, 1);
268     ffrt_queue_t queue_handle = ffrt_queue_create(static_cast<ffrt_queue_type_t>(ffrt_queue_eventhandler_adapter),
269         "queue_dump", &queue_attr);
270     char* buf = new char[BUFFER_SIZE];
271     // 提交10个任务并等待任务执行完成(任务名称:task1)
272     QueueDumpTask1Test(queue_handle, buf);
273     // 提交30个任务并等待任务执行完成(任务名称:task2)
274     QueueDumpTask2Test(queue_handle, buf);
275     // 提交1个睡眠3s的任务(任务名称:task3)
276     QueueDumpTask3Test(queue_handle, buf);
277     // 5种优先级各提交10个任务
278     QueueDumpPriorityTest(queue_handle, buf);
279     // 提交600个优先级为ffrt_inner_queue_priority_high的任务
280     QueueDumpMaxDumpSizeTest(queue_handle, buf);
281     // 验证ffrt_queue_size_dump结果
282     EXPECT_EQ(ffrt_queue_size_dump(queue_handle, ffrt_inner_queue_priority_immediate), TASK_NUM_10);
283     EXPECT_EQ(ffrt_queue_size_dump(queue_handle, ffrt_inner_queue_priority_high), TASK_NUM_610);
284     EXPECT_EQ(ffrt_queue_size_dump(queue_handle, ffrt_inner_queue_priority_low), TASK_NUM_10);
285     EXPECT_EQ(ffrt_queue_size_dump(queue_handle, ffrt_inner_queue_priority_idle), TASK_NUM_10);
286     EXPECT_EQ(ffrt_queue_size_dump(queue_handle, ffrt_inner_queue_priority_vip), TASK_NUM_10);
287 
288     delete[] buf;
289     ffrt_queue_destroy(queue_handle);
290     ffrt_queue_attr_destroy(&queue_attr);
291 }
292