• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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