blob: 2553d40ea6a3aabc089c8c0caa21977cd25102f0 [file] [log] [blame]
Primiano Tucci401a4732022-01-19 00:26:49 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "perfetto/base/build_config.h"
18
19#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
20 PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
21
22#include "perfetto/base/build_config.h"
23#include "perfetto/base/logging.h"
24#include "perfetto/ext/base/file_utils.h"
25#include "perfetto/ext/base/scoped_file.h"
26#include "perfetto/ext/base/string_utils.h"
27#include "perfetto/ext/base/temp_file.h"
28#include "perfetto/ext/base/utils.h"
29#include "perfetto/ext/traced/traced.h"
30#include "perfetto/ext/tracing/core/commit_data_request.h"
31#include "perfetto/ext/tracing/core/trace_packet.h"
32#include "perfetto/ext/tracing/core/tracing_service.h"
33#include "perfetto/protozero/scattered_heap_buffer.h"
34#include "perfetto/tracing/core/tracing_service_state.h"
35#include "src/base/test/test_task_runner.h"
36#include "src/base/test/utils.h"
37#include "src/traced/probes/ftrace/ftrace_controller.h"
38#include "src/traced/probes/ftrace/ftrace_procfs.h"
39#include "test/gtest_and_gmock.h"
40#include "test/test_helper.h"
41
42#include "protos/perfetto/config/test_config.gen.h"
43#include "protos/perfetto/config/trace_config.gen.h"
44#include "protos/perfetto/trace/ftrace/ftrace.gen.h"
45#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
46#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
47#include "protos/perfetto/trace/ftrace/ftrace_stats.gen.h"
48#include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
49#include "protos/perfetto/trace/test_event.gen.h"
50#include "protos/perfetto/trace/trace.gen.h"
51#include "protos/perfetto/trace/trace_packet.gen.h"
52#include "protos/perfetto/trace/trace_packet.pbzero.h"
53
54#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
55#include "test/android_test_utils.h"
56#endif
57
58namespace perfetto {
59
60namespace {
61
62using ::testing::ContainsRegex;
63using ::testing::Each;
64using ::testing::ElementsAreArray;
65using ::testing::HasSubstr;
66using ::testing::Property;
67using ::testing::SizeIs;
68
69class PerfettoFtraceIntegrationTest : public ::testing::Test {
70 public:
71 void SetUp() override {
72 ftrace_procfs_ = FtraceProcfs::CreateGuessingMountPoint();
73
74// On android we do expect that tracefs is accessible, both in the case of
75// running as part of traced/probes system daemons and shell. On Linux this is
76// up to the system admin, don't hard fail.
77#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
78 if (!ftrace_procfs_) {
79 PERFETTO_ELOG(
80 "Cannot acces tracefs. On Linux you need to manually run `sudo chown "
81 "-R $USER /sys/kernel/tracing` to enable these tests. Skipping");
82 GTEST_SKIP();
83 } else {
84 // Recent kernels set tracing_on=1 by default. On Android this is
85 // disabled by initrc scripts. Be tolerant on Linux where we don't have
86 // that and force disable ftrace.
87 ftrace_procfs_->SetTracingOn(false);
88 }
89#endif
90 }
91
92 std::unique_ptr<FtraceProcfs> ftrace_procfs_;
93};
94
95} // namespace
96
97TEST_F(PerfettoFtraceIntegrationTest, TestFtraceProducer) {
98 base::TestTaskRunner task_runner;
99
100 TestHelper helper(&task_runner);
101 helper.StartServiceIfRequired();
102
103#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
104 ProbesProducerThread probes(GetTestProducerSockName());
105 probes.Connect();
106#endif
107
108 helper.ConnectConsumer();
109 helper.WaitForConsumerConnect();
110
111 TraceConfig trace_config;
112 trace_config.add_buffers()->set_size_kb(1024);
113 trace_config.set_duration_ms(3000);
114
115 auto* ds_config = trace_config.add_data_sources()->mutable_config();
116 ds_config->set_name("linux.ftrace");
117 ds_config->set_target_buffer(0);
118
119 protos::gen::FtraceConfig ftrace_config;
120 ftrace_config.add_ftrace_events("sched_switch");
121 ftrace_config.add_ftrace_events("bar");
122 ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
123
124 helper.StartTracing(trace_config);
125 helper.WaitForTracingDisabled();
126
127 helper.ReadData();
128 helper.WaitForReadData();
129
130 const auto& packets = helper.trace();
131 ASSERT_GT(packets.size(), 0u);
132
133 for (const auto& packet : packets) {
134 for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
135 ASSERT_TRUE(packet.ftrace_events()
136 .event()[static_cast<size_t>(ev)]
137 .has_sched_switch());
138 }
139 }
140}
141
142TEST_F(PerfettoFtraceIntegrationTest, TestFtraceFlush) {
143 base::TestTaskRunner task_runner;
144
145 TestHelper helper(&task_runner);
146 helper.StartServiceIfRequired();
147
148#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
149 ProbesProducerThread probes(GetTestProducerSockName());
150 probes.Connect();
151#endif
152
153 helper.ConnectConsumer();
154 helper.WaitForConsumerConnect();
155
156 // Wait for the traced_probes service to connect. We want to start tracing
157 // only after it connects, otherwise we'll start a tracing session with 0
158 // producers connected (which is valid but not what we want here).
159 helper.WaitForDataSourceConnected("linux.ftrace");
160
161 TraceConfig trace_config;
162 trace_config.add_buffers()->set_size_kb(32);
163 trace_config.set_duration_ms(kDefaultTestTimeoutMs);
164
165 auto* ds_config = trace_config.add_data_sources()->mutable_config();
166 ds_config->set_name("linux.ftrace");
167
168 protos::gen::FtraceConfig ftrace_config;
169 ftrace_config.add_ftrace_events("print");
170 ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
171
172 helper.StartTracing(trace_config);
173
174 // Wait for traced_probes to start.
175 helper.WaitFor([&] { return ftrace_procfs_->IsTracingEnabled(); }, "ftrace");
176
177 // Do a first flush just to synchronize with the producer. The problem here
178 // is that, on a Linux workstation, the producer can take several seconds just
179 // to get to the point where it is fully ready. We use the flush ack as a
180 // synchronization point.
181 helper.FlushAndWait(kDefaultTestTimeoutMs);
182
183 const char kMarker[] = "just_one_event";
184 EXPECT_TRUE(ftrace_procfs_->WriteTraceMarker(kMarker));
185
186 // This is the real flush we are testing.
187 helper.FlushAndWait(kDefaultTestTimeoutMs);
188
189 helper.DisableTracing();
190 helper.WaitForTracingDisabled(kDefaultTestTimeoutMs);
191
192 helper.ReadData();
193 helper.WaitForReadData();
194
195 int marker_found = 0;
196 for (const auto& packet : helper.trace()) {
197 for (int i = 0; i < packet.ftrace_events().event_size(); i++) {
198 const auto& ev = packet.ftrace_events().event()[static_cast<size_t>(i)];
199 if (ev.has_print() && ev.print().buf().find(kMarker) != std::string::npos)
200 marker_found++;
201 }
202 }
203 ASSERT_EQ(marker_found, 1);
204}
205
206// Disable this test:
207// 1. On cuttlefish (x86-kvm). It's too slow when running on GCE (b/171771440).
208// We cannot change the length of the production code in
209// CanReadKernelSymbolAddresses() to deal with it.
210// 2. On user (i.e. non-userdebug) builds. As that doesn't work there by design.
211// 3. On ARM builds, because they fail on our CI.
212#if (PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) && defined(__i386__)) || \
213 defined(__arm__)
214#define MAYBE_KernelAddressSymbolization DISABLED_KernelAddressSymbolization
215#else
216#define MAYBE_KernelAddressSymbolization KernelAddressSymbolization
217#endif
218TEST_F(PerfettoFtraceIntegrationTest, MAYBE_KernelAddressSymbolization) {
219 // On Android in-tree builds (TreeHugger): this test must always run to
220 // prevent selinux / property-related regressions. However it can run only on
221 // userdebug.
222 // On standalone builds and Linux, this can be optionally skipped because
223 // there it requires root to lower kptr_restrict.
224#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
225 if (!IsDebuggableBuild())
226 GTEST_SKIP();
227#else
228 if (geteuid() != 0)
229 GTEST_SKIP();
230#endif
231
232 base::TestTaskRunner task_runner;
233
234 TestHelper helper(&task_runner);
235 helper.StartServiceIfRequired();
236
237#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
238 ProbesProducerThread probes(GetTestProducerSockName());
239 probes.Connect();
240#endif
241
242 helper.ConnectConsumer();
243 helper.WaitForConsumerConnect();
244
245 TraceConfig trace_config;
246 trace_config.add_buffers()->set_size_kb(1024);
247
248 auto* ds_config = trace_config.add_data_sources()->mutable_config();
249 ds_config->set_name("linux.ftrace");
250 protos::gen::FtraceConfig ftrace_cfg;
251 ftrace_cfg.set_symbolize_ksyms(true);
252 ftrace_cfg.set_initialize_ksyms_synchronously_for_testing(true);
253 ds_config->set_ftrace_config_raw(ftrace_cfg.SerializeAsString());
254
255 helper.StartTracing(trace_config);
256
257 // Synchronize with the ftrace data source. The kernel symbol map is loaded
258 // at this point.
259 helper.FlushAndWait(kDefaultTestTimeoutMs);
260 helper.DisableTracing();
261 helper.WaitForTracingDisabled();
262 helper.ReadData();
263 helper.WaitForReadData();
264
265 const auto& packets = helper.trace();
266 ASSERT_GT(packets.size(), 0u);
267
268 int symbols_parsed = -1;
269 for (const auto& packet : packets) {
270 if (!packet.has_ftrace_stats())
271 continue;
272 if (packet.ftrace_stats().phase() != protos::gen::FtraceStats::END_OF_TRACE)
273 continue;
274 symbols_parsed =
275 static_cast<int>(packet.ftrace_stats().kernel_symbols_parsed());
276 }
277 ASSERT_GT(symbols_parsed, 100);
278}
279
280} // namespace perfetto
281#endif // OS_ANDROID || OS_LINUX