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