1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 <dlfcn.h>
16 #include <fcntl.h>
17 #include <fstream>
18 #include <gtest/gtest.h>
19 #include <string>
20 #include <thread>
21 #include <type_traits>
22 #include <unistd.h>
23
24 #include "file_utils.h"
25 #include "flow_controller.h"
26
27 using namespace testing::ext;
28
29 namespace {
30 constexpr uint32_t BUFFER_SIZE_KB = 256;
31 constexpr uint32_t BUFFER_SIZE_MIN_KB = 63;
32 constexpr uint32_t BUFFER_SIZE_MAX_KB = 64 * 1024 + 1;
33 constexpr uint32_t FLUSH_INTERVAL_MS = 1000;
34 constexpr uint32_t FLUSH_THRESHOLD_KB = 1024;
35 constexpr uint32_t TRACE_PERIOD_MS = 500;
36 constexpr uint32_t TEST_CPU_NUM = 4;
37 constexpr uint32_t TRACE_TIME = 3;
38 constexpr uint32_t BUFFER_SIZE = 2 * 1024 * 1024;
39 RandomWriteCtx g_writeCtx = {};
40 std::unique_ptr<uint8_t[]> g_buffer = nullptr;
41 using WriterStructPtr = std::unique_ptr<WriterStruct>::pointer;
42 using ConstVoidPtr = std::unique_ptr<const void>::pointer;
43 class FlowControllerTest : public ::testing::Test {
44 protected:
SetUp()45 void SetUp() override {}
TearDown()46 void TearDown() override {}
47 };
48
WriteFunc(WriterStructPtr writer,ConstVoidPtr data,size_t size)49 long WriteFunc(WriterStructPtr writer, ConstVoidPtr data, size_t size)
50 {
51 if (writer == nullptr || data == nullptr || size <= 0) {
52 return -1;
53 }
54
55 return 0;
56 }
57
FlushFunc(WriterStructPtr writer)58 bool FlushFunc(WriterStructPtr writer)
59 {
60 if (writer == nullptr) {
61 return false;
62 }
63 return true;
64 }
65
StartReportFunc(WriterStructPtr writer)66 RandomWriteCtx* StartReportFunc(WriterStructPtr writer)
67 {
68 if (writer == nullptr) {
69 return nullptr;
70 }
71
72 g_writeCtx.getMemory = [](RandomWriteCtx* ctx, uint32_t size, uint8_t** memory, uint32_t* offset) -> bool {
73 if (size > BUFFER_SIZE) {
74 return false;
75 }
76
77 *memory = g_buffer.get();
78 *offset = 0;
79 return true;
80 };
81 g_writeCtx.seek = [](RandomWriteCtx* ctx, uint32_t offset) -> bool {
82 return true;
83 };
84
85 return &g_writeCtx;
86 }
87
FinishReportFunc(WriterStructPtr writer,int32_t size)88 void FinishReportFunc(WriterStructPtr writer, int32_t size)
89 {
90 return;
91 }
92
93 /*
94 * @tc.name: SetWriter
95 * @tc.desc: test FlowController::SetWriter.
96 * @tc.type: FUNC
97 */
98 HWTEST_F(FlowControllerTest, SetWriter, TestSize.Level1)
99 {
100 OHOS::Profiler::Plugins::FlowController controller;
101 WriterStruct writer = {WriteFunc, FlushFunc};
102 EXPECT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
103 }
104
105 /*
106 * @tc.name: LoadConfig
107 * @tc.desc: test FlowController::LoadConfig.
108 * @tc.type: FUNC
109 */
110 HWTEST_F(FlowControllerTest, LoadConfig, TestSize.Level1)
111 {
112 OHOS::Profiler::Plugins::FlowController controller;
113 TracePluginConfig config;
114
115 // set writer
116 WriterStruct writer = {WriteFunc, FlushFunc};
117 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
118
119 // set config
120 config.add_ftrace_events("sched/sched_switch");
121 config.set_buffer_size_kb(BUFFER_SIZE_KB);
122 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
123 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
124 config.set_parse_ksyms(true);
125 config.set_clock("global");
126 config.set_trace_period_ms(TRACE_PERIOD_MS);
127 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
128 std::vector<uint8_t> configData(config.ByteSizeLong());
129 int ret = config.SerializeToArray(configData.data(), configData.size());
130 ASSERT_GT(ret, 0);
131 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
132 }
133
134 /*
135 * @tc.name: LoadConfig
136 * @tc.desc: test FlowController::LoadConfig.
137 * @tc.type: FUNC
138 */
139 HWTEST_F(FlowControllerTest, SetMinBufForLoadConfig, TestSize.Level1)
140 {
141 OHOS::Profiler::Plugins::FlowController controller;
142 TracePluginConfig config;
143
144 // set writer
145 WriterStruct writer = {WriteFunc, FlushFunc};
146 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
147
148 // set config
149 config.set_buffer_size_kb(BUFFER_SIZE_MIN_KB);
150 std::vector<uint8_t> configData(config.ByteSizeLong());
151 int ret = config.SerializeToArray(configData.data(), configData.size());
152 ASSERT_GT(ret, 0);
153 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), -1);
154 }
155
156 /*
157 * @tc.name: LoadConfig
158 * @tc.desc: test FlowController::LoadConfig.
159 * @tc.type: FUNC
160 */
161 HWTEST_F(FlowControllerTest, SetMaxBufForLoadConfig, TestSize.Level1)
162 {
163 OHOS::Profiler::Plugins::FlowController controller;
164 TracePluginConfig config;
165
166 // set writer
167 WriterStruct writer = {WriteFunc, FlushFunc};
168 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
169
170 // set config
171 config.set_buffer_size_kb(BUFFER_SIZE_MAX_KB);
172 std::vector<uint8_t> configData(config.ByteSizeLong());
173 int ret = config.SerializeToArray(configData.data(), configData.size());
174 ASSERT_GT(ret, 0);
175 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), -1);
176 }
177
178 /*
179 * @tc.name: LoadConfig
180 * @tc.desc: test FlowController::LoadConfig.
181 * @tc.type: FUNC
182 */
183 HWTEST_F(FlowControllerTest, SetTracePeriodForLoadConfig, TestSize.Level1)
184 {
185 OHOS::Profiler::Plugins::FlowController controller;
186 TracePluginConfig config;
187
188 // set writer
189 WriterStruct writer = {WriteFunc, FlushFunc};
190 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
191
192 // set config
193 config.add_hitrace_apps("ftrace_plugin_ut");
194 config.add_hitrace_categories("idle");
195 config.add_hitrace_categories("ability");
196 std::vector<uint8_t> configData(config.ByteSizeLong());
197 int ret = config.SerializeToArray(configData.data(), configData.size());
198 ASSERT_GT(ret, 0);
199 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
200 }
201
202 /*
203 * @tc.name: LoadConfig
204 * @tc.desc: test FlowController::LoadConfig.
205 * @tc.type: FUNC
206 */
207 HWTEST_F(FlowControllerTest, SetHitraceAppForLoadConfig, TestSize.Level1)
208 {
209 OHOS::Profiler::Plugins::FlowController controller;
210 TracePluginConfig config;
211
212 // set writer
213 WriterStruct writer = {WriteFunc, FlushFunc};
214 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
215
216 // set config
217 config.add_ftrace_events("sched/sched_switch");
218 config.add_hitrace_categories("ability");
219 config.set_trace_period_ms(0);
220 std::vector<uint8_t> configData(config.ByteSizeLong());
221 int ret = config.SerializeToArray(configData.data(), configData.size());
222 ASSERT_GT(ret, 0);
223 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
224 }
225
226 /*
227 * @tc.name: StartCapture
228 * @tc.desc: test FlowController::StartCapture.
229 * @tc.type: FUNC
230 */
231 HWTEST_F(FlowControllerTest, StartCapture, TestSize.Level1)
232 {
233 OHOS::Profiler::Plugins::FlowController controller;
234 TracePluginConfig config;
235
236 // set writer
237 WriterStruct writer = {WriteFunc, FlushFunc};
238 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
239
240 // set config
241 config.add_ftrace_events("sched/sched_switch");
242 config.add_hitrace_categories("ability");
243 config.add_hitrace_categories("ace");
244 config.set_buffer_size_kb(BUFFER_SIZE_KB);
245 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
246 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
247 config.set_parse_ksyms(true);
248 config.set_clock("global");
249 config.set_trace_period_ms(TRACE_PERIOD_MS);
250 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
251 std::vector<uint8_t> configData(config.ByteSizeLong());
252 int ret = config.SerializeToArray(configData.data(), configData.size());
253 ASSERT_GT(ret, 0);
254 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
255
256 EXPECT_EQ(controller.StartCapture(), 0);
257 EXPECT_EQ(controller.StopCapture(), 0);
258
259 if (OHOS::Profiler::Plugins::FtraceFsOps::GetInstance().IsHmKernel() == false) {
260 controller.parseMode_ = TracePluginConfig_ParseMode_DELAY_PARSE;
261 EXPECT_EQ(controller.StartCapture(), 0);
262 EXPECT_EQ(controller.StopCapture(), 0);
263 }
264 }
265
266 /*
267 * @tc.name: Hitrace Apps
268 * @tc.desc: test FlowController::hitrace_apps.
269 * @tc.type: FUNC
270 */
271 HWTEST_F(FlowControllerTest, HitraceApps, TestSize.Level1)
272 {
273 OHOS::Profiler::Plugins::FlowController controller;
274 TracePluginConfig config;
275
276 // set writer
277 WriterStruct writer = {WriteFunc, FlushFunc};
278 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
279
280 // set config
281 config.add_hitrace_apps("render_service");
282 config.add_hitrace_categories("ability");
283 config.add_hitrace_categories("ace");
284 config.add_hitrace_categories("binder");
285 config.add_hitrace_categories("graphic");
286 config.add_hitrace_categories("idle");
287 config.set_buffer_size_kb(BUFFER_SIZE_KB);
288 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
289 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
290 config.set_parse_ksyms(true);
291 config.set_clock("global");
292 config.set_trace_period_ms(TRACE_PERIOD_MS);
293 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
294 std::vector<uint8_t> configData(config.ByteSizeLong());
295 int ret = config.SerializeToArray(configData.data(), configData.size());
296 ASSERT_GT(ret, 0);
297 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
298
299 EXPECT_EQ(controller.StartCapture(), 0);
300 EXPECT_EQ(controller.StopCapture(), 0);
301
302 if (OHOS::Profiler::Plugins::FtraceFsOps::GetInstance().IsHmKernel() == false) {
303 controller.parseMode_ = TracePluginConfig_ParseMode_DELAY_PARSE;
304 EXPECT_EQ(controller.StartCapture(), 0);
305 EXPECT_EQ(controller.StopCapture(), 0);
306 }
307 }
308
309 /*
310 * @tc.name: StartCapture
311 * @tc.desc: test FlowController::StartCaptureWithBinder.
312 * @tc.type: FUNC
313 */
314 HWTEST_F(FlowControllerTest, StartCaptureWithBinder, TestSize.Level1)
315 {
316 OHOS::Profiler::Plugins::FlowController controller;
317 TracePluginConfig config;
318
319 // set writer
320 WriterStruct writer = {WriteFunc, FlushFunc};
321 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
322
323 // set config
324 config.add_ftrace_events("binder/binder_transaction");
325 config.add_hitrace_categories("ability");
326 config.add_hitrace_categories("ace");
327 config.set_buffer_size_kb(BUFFER_SIZE_KB);
328 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
329 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
330 config.set_parse_ksyms(true);
331 config.set_clock("global");
332 config.set_trace_period_ms(TRACE_PERIOD_MS);
333 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
334 std::vector<uint8_t> configData(config.ByteSizeLong());
335 int ret = config.SerializeToArray(configData.data(), configData.size());
336 ASSERT_GT(ret, 0);
337 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
338
339 EXPECT_EQ(controller.StartCapture(), 0);
340 EXPECT_EQ(controller.StopCapture(), 0);
341
342 if (OHOS::Profiler::Plugins::FtraceFsOps::GetInstance().IsHmKernel() == false) {
343 controller.parseMode_ = TracePluginConfig_ParseMode_DELAY_PARSE;
344 EXPECT_EQ(controller.StartCapture(), 0);
345 EXPECT_EQ(controller.StopCapture(), 0);
346 }
347 }
348
349 /*
350 * @tc.name: frace_module
351 * @tc.desc: test Framework.
352 * @tc.type: FUNC
353 */
354 HWTEST_F(FlowControllerTest, TestFramework, TestSize.Level1)
355 {
356 std::string path = std::string("libftrace_plugin.z.so");
357 auto handle = dlopen(path.c_str(), RTLD_LAZY);
358 EXPECT_NE(handle, nullptr);
359 PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
360 EXPECT_NE(plugin, nullptr);
361 EXPECT_STREQ(plugin->name, "ftrace-plugin");
362
363 // set config
364 TracePluginConfig config;
365 config.add_ftrace_events("sched/sched_switch");
366 config.add_hitrace_categories("ability");
367 config.add_hitrace_categories("ace");
368 config.set_buffer_size_kb(BUFFER_SIZE_KB);
369 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
370 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
371 config.set_parse_ksyms(true);
372 config.set_clock("global");
373 config.set_trace_period_ms(TRACE_PERIOD_MS);
374 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
375 std::vector<uint8_t> configData(config.ByteSizeLong());
376 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
377
378 // test framework process
379 WriterStruct writer = {WriteFunc, FlushFunc};
380 std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
381 EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
382 EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
383 EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
384 }
385
386 /*
387 * @tc.name: frace_module
388 * @tc.desc: test ftrace plugin based on resource files.
389 * @tc.type: FUNC
390 */
391 HWTEST_F(FlowControllerTest, TestFrameworkWithFile, TestSize.Level1)
392 {
393 // set writer
394 WriterStruct writer = {WriteFunc, FlushFunc};
395 OHOS::Profiler::Plugins::FlowController controller;
396 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
397 controller.SetTestInfo(TEST_CPU_NUM, "/data/local/tmp/");
398
399 // set config
400 TracePluginConfig config;
401 config.add_ftrace_events("sched/sched_switch");
402 config.add_hitrace_categories("ability");
403 config.add_hitrace_categories("ace");
404 config.set_buffer_size_kb(BUFFER_SIZE);
405 config.set_trace_period_ms(TRACE_PERIOD_MS);
406 std::vector<uint8_t> configData(config.ByteSizeLong());
407 int ret = config.SerializeToArray(configData.data(), configData.size());
408 ASSERT_GT(ret, 0);
409 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
410
411 EXPECT_EQ(controller.StartCapture(), 0);
412 sleep(TRACE_TIME);
413 EXPECT_EQ(controller.StopCapture(), 0);
414 }
415
416 /*
417 * @tc.name: frace_module
418 * @tc.desc: test ftrace plugin encoder based on resource files.
419 * @tc.type: FUNC
420 */
421 HWTEST_F(FlowControllerTest, TestFrameworkEncoder, TestSize.Level1)
422 {
423 g_buffer = std::make_unique<uint8_t[]>(BUFFER_SIZE);
424 ASSERT_NE(g_buffer.get(), nullptr);
425
426 // set writer
427 WriterStruct writer = {WriteFunc, FlushFunc, StartReportFunc, FinishReportFunc, false};
428 OHOS::Profiler::Plugins::FlowController controller;
429 ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
430 controller.SetTestInfo(TEST_CPU_NUM, "/data/local/tmp/");
431
432 // set config
433 TracePluginConfig config;
434 config.add_ftrace_events("sched/sched_switch");
435 config.add_hitrace_categories("ability");
436 config.add_hitrace_categories("ace");
437 config.set_buffer_size_kb(BUFFER_SIZE);
438 config.set_trace_period_ms(TRACE_PERIOD_MS);
439 std::vector<uint8_t> configData(config.ByteSizeLong());
440 int ret = config.SerializeToArray(configData.data(), configData.size());
441 ASSERT_GT(ret, 0);
442 EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
443
444 EXPECT_EQ(controller.StartCapture(), 0);
445 sleep(TRACE_TIME);
446 EXPECT_EQ(controller.StopCapture(), 0);
447 }
448 } // namespace
449