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