• 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: frace_module
268  * @tc.desc: test Framework.
269  * @tc.type: FUNC
270  */
271 HWTEST_F(FlowControllerTest, TestFramework, TestSize.Level1)
272 {
273     std::string path = std::string("libftrace_plugin.z.so");
274     auto handle = dlopen(path.c_str(), RTLD_LAZY);
275     EXPECT_NE(handle, nullptr);
276     PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
277     EXPECT_NE(plugin, nullptr);
278     EXPECT_STREQ(plugin->name, "ftrace-plugin");
279 
280     // set config
281     TracePluginConfig config;
282     config.add_ftrace_events("sched/sched_switch");
283     config.add_hitrace_categories("ability");
284     config.add_hitrace_categories("ace");
285     config.set_buffer_size_kb(BUFFER_SIZE_KB);
286     config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
287     config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
288     config.set_parse_ksyms(true);
289     config.set_clock("global");
290     config.set_trace_period_ms(TRACE_PERIOD_MS);
291     config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
292     std::vector<uint8_t> configData(config.ByteSizeLong());
293     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
294 
295     // test framework process
296     WriterStruct writer = {WriteFunc, FlushFunc};
297     std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
298     EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
299     EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
300     EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
301 }
302 
303 /*
304  * @tc.name: frace_module
305  * @tc.desc: test ftrace plugin based on resource files.
306  * @tc.type: FUNC
307  */
308 HWTEST_F(FlowControllerTest, TestFrameworkWithFile, TestSize.Level1)
309 {
310     // set writer
311     WriterStruct writer = {WriteFunc, FlushFunc};
312     OHOS::Profiler::Plugins::FlowController controller;
313     ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
314     controller.SetTestInfo(TEST_CPU_NUM, "/data/local/tmp/");
315 
316     // set config
317     TracePluginConfig config;
318     config.add_ftrace_events("sched/sched_switch");
319     config.add_hitrace_categories("ability");
320     config.add_hitrace_categories("ace");
321     config.set_buffer_size_kb(BUFFER_SIZE);
322     config.set_trace_period_ms(TRACE_PERIOD_MS);
323     std::vector<uint8_t> configData(config.ByteSizeLong());
324     int ret = config.SerializeToArray(configData.data(), configData.size());
325     ASSERT_GT(ret, 0);
326     EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
327 
328     EXPECT_EQ(controller.StartCapture(), 0);
329     sleep(TRACE_TIME);
330     EXPECT_EQ(controller.StopCapture(), 0);
331 }
332 
333 /*
334  * @tc.name: frace_module
335  * @tc.desc: test ftrace plugin encoder based on resource files.
336  * @tc.type: FUNC
337  */
338 HWTEST_F(FlowControllerTest, TestFrameworkEncoder, TestSize.Level1)
339 {
340     g_buffer = std::make_unique<uint8_t[]>(BUFFER_SIZE);
341     ASSERT_NE(g_buffer.get(), nullptr);
342 
343     // set writer
344     WriterStruct writer = {WriteFunc, FlushFunc, StartReportFunc, FinishReportFunc, false};
345     OHOS::Profiler::Plugins::FlowController controller;
346     ASSERT_EQ(controller.SetWriter(static_cast<WriterStructPtr>(&writer)), 0);
347     controller.SetTestInfo(TEST_CPU_NUM, "/data/local/tmp/");
348 
349     // set config
350     TracePluginConfig config;
351     config.add_ftrace_events("sched/sched_switch");
352     config.add_hitrace_categories("ability");
353     config.add_hitrace_categories("ace");
354     config.set_buffer_size_kb(BUFFER_SIZE);
355     config.set_trace_period_ms(TRACE_PERIOD_MS);
356     std::vector<uint8_t> configData(config.ByteSizeLong());
357     int ret = config.SerializeToArray(configData.data(), configData.size());
358     ASSERT_GT(ret, 0);
359     EXPECT_EQ(controller.LoadConfig(configData.data(), configData.size()), 0);
360 
361     EXPECT_EQ(controller.StartCapture(), 0);
362     sleep(TRACE_TIME);
363     EXPECT_EQ(controller.StopCapture(), 0);
364 }
365 } // namespace
366