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 <fcntl.h>
16 #include <gtest/gtest.h>
17 #include <thread>
18 #include <unistd.h>
19
20 #include "flow_controller.h"
21 #include "ftrace_fs_ops.h"
22 #include "ftrace_parser.h"
23
24 using FTRACE_NS::FlowController;
25 using FTRACE_NS::FtraceFsOps;
26 using FTRACE_NS::FtraceParser;
27 using FTRACE_NS::PerCpuStats;
28 using testing::ext::TestSize;
29
30 namespace {
31 #ifndef PAGE_SIZE
32 constexpr uint32_t PAGE_SIZE = 4096;
33 #endif
34
35 constexpr uint32_t BUFFER_SIZE_KB = 256;
36 constexpr uint32_t FLUSH_INTERVAL_MS = 100;
37 constexpr uint32_t FLUSH_THRESHOLD_KB = 1024;
38 constexpr uint32_t TRACE_PERIOD_MS = 500;
39 using WriterStructPtr = std::unique_ptr<WriterStruct>::pointer;
40 using ConstVoidPtr = std::unique_ptr<const void>::pointer;
41
42 long WriteFunc(WriterStructPtr writer, ConstVoidPtr data, size_t size);
43 bool FlushFunc(WriterStructPtr writer);
44
45 class FtraceParserTest : public ::testing::Test {
46 protected:
SetUpTestCase()47 static void SetUpTestCase()
48 {
49 // start tracing sched_switch event
50 FlowController controller;
51 TracePluginConfig config;
52
53 // set writer
54 WriterStruct writer = {WriteFunc, FlushFunc};
55 controller.SetWriter(static_cast<WriterStructPtr>(&writer));
56 // stop capture firstly
57 controller.StopCapture();
58 // set config
59 config.add_ftrace_events("sched/sched_switch");
60 config.add_hitrace_categories("ability");
61 config.add_hitrace_categories("ace");
62 config.set_buffer_size_kb(BUFFER_SIZE_KB);
63 config.set_flush_interval_ms(FLUSH_INTERVAL_MS);
64 config.set_flush_threshold_kb(FLUSH_THRESHOLD_KB);
65 config.set_parse_ksyms(true);
66 config.set_clock("global");
67 config.set_trace_period_ms(TRACE_PERIOD_MS);
68 config.set_raw_data_prefix("/data/local/tmp/raw_trace_");
69 std::vector<uint8_t> configData(config.ByteSizeLong());
70 config.SerializeToArray(configData.data(), configData.size());
71 controller.LoadConfig(configData.data(), configData.size());
72 controller.StartCapture();
73 sleep(1);
74 controller.StopCapture();
75 }
76
SetUp()77 void SetUp() override {}
TearDown()78 void TearDown() override {}
79 };
80
WriteFunc(WriterStructPtr writer,ConstVoidPtr data,size_t size)81 long WriteFunc(WriterStructPtr writer, ConstVoidPtr data, size_t size)
82 {
83 if (writer == nullptr || data == nullptr || size <= 0) {
84 return -1;
85 }
86
87 return 0;
88 }
89
FlushFunc(WriterStructPtr writer)90 bool FlushFunc(WriterStructPtr writer)
91 {
92 if (writer == nullptr) {
93 return false;
94 }
95 return true;
96 }
97
98 /*
99 * @tc.name: Init
100 * @tc.desc: test FtraceParser::Init with normal case.
101 * @tc.type: FUNC
102 */
103 HWTEST_F(FtraceParserTest, Init, TestSize.Level1)
104 {
105 FtraceParser parser;
106 EXPECT_TRUE(parser.Init());
107 }
108
109 /*
110 * @tc.name: SetupEvent
111 * @tc.desc: test FtraceParser::Init with normal case.
112 * @tc.type: FUNC
113 */
114 HWTEST_F(FtraceParserTest, SetupEvent, TestSize.Level1)
115 {
116 FtraceParser parser;
117 EXPECT_TRUE(parser.SetupEvent("sched", "sched_switch"));
118 }
119
120 /*
121 * @tc.name: ParseSavedTgid
122 * @tc.desc: test FtraceParser::ParseSavedTgid with normal case.
123 * @tc.type: FUNC
124 */
125 HWTEST_F(FtraceParserTest, ParseSavedTgid, TestSize.Level1)
126 {
127 FtraceParser parser;
128 EXPECT_TRUE(parser.ParseSavedTgid(FtraceFsOps::GetInstance().GetSavedTgids()));
129 }
130
131 /*
132 * @tc.name: ParseSavedCmdlines
133 * @tc.desc: test FtraceParser::ParseSavedCmdlines with normal case.
134 * @tc.type: FUNC
135 */
136 HWTEST_F(FtraceParserTest, ParseSavedCmdlines, TestSize.Level1)
137 {
138 FtraceParser parser;
139 EXPECT_TRUE(parser.ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines()));
140 }
141
142 /*
143 * @tc.name: ParsePerCpuStatus
144 * @tc.desc: test FtraceParser::ParsePerCpuStatus with normal case.
145 * @tc.type: FUNC
146 */
147 HWTEST_F(FtraceParserTest, ParsePerCpuStatus, TestSize.Level1)
148 {
149 if (!FtraceFsOps::GetInstance().IsHmKernel()) {
150 FtraceParser parser;
151 PerCpuStats perCpuStats = {};
152 EXPECT_FALSE(parser.ParsePerCpuStatus(perCpuStats, ""));
153
154 std::string perCpuStatsStr = FtraceFsOps::GetInstance().GetPerCpuStats(0);
155 EXPECT_TRUE(parser.ParsePerCpuStatus(perCpuStats, perCpuStatsStr));
156 }
157 }
158
159 /*
160 * @tc.name: ParsePage
161 * @tc.desc: test SubEventParser::ParsePage with normal case.
162 * @tc.type: FUNC
163 */
164 HWTEST_F(FtraceParserTest, ParsePage, TestSize.Level1)
165 {
166 std::vector<uint8_t> buffer(PAGE_SIZE, 0);
167 std::string traceRaw;
168 if (FtraceFsOps::GetInstance().IsHmKernel()) {
169 traceRaw = FtraceFsOps::GetInstance().GetHmRawTracePath();
170 } else {
171 traceRaw = FtraceFsOps::GetInstance().GetRawTracePath(0);
172 }
173 int fd = open(traceRaw.c_str(), O_EXCL);
174 EXPECT_NE(fd, -1);
175
176 EXPECT_TRUE(FtraceFsOps::GetInstance().ClearTraceBuffer());
177 EXPECT_TRUE(FtraceFsOps::GetInstance().EnableEvent("sched", "sched_switch"));
178 EXPECT_TRUE(FtraceFsOps::GetInstance().EnableTracing());
179 std::this_thread::yield();
180 EXPECT_EQ(read(fd, buffer.data(), buffer.size()), PAGE_SIZE);
181 EXPECT_TRUE(FtraceFsOps::GetInstance().DisableTracing());
182
183 if (!FtraceFsOps::GetInstance().IsHmKernel()) {
184 FtraceCpuDetailMsg cpuDetailMsg = {};
185 FtraceParser parser;
186 FtraceEvent* event = nullptr;
187 parser.Init();
188 EXPECT_TRUE(parser.ParsePage(cpuDetailMsg, buffer.data(), buffer.size(), event));
189 EXPECT_EQ(close(fd), 0);
190 }
191 }
192 } // namespace