1 /*
2 * Copyright 2024 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 "tracing_perfetto.h"
18
19 #include <android_os.h>
20 #include <flag_macros.h>
21 #include <thread>
22 #include <unistd.h>
23
24 #include "gtest/gtest.h"
25 #include "perfetto/public/abi/data_source_abi.h"
26 #include "perfetto/public/abi/heap_buffer.h"
27 #include "perfetto/public/abi/pb_decoder_abi.h"
28 #include "perfetto/public/abi/tracing_session_abi.h"
29 #include "perfetto/public/abi/track_event_abi.h"
30 #include "perfetto/public/data_source.h"
31 #include "perfetto/public/pb_decoder.h"
32 #include "perfetto/public/producer.h"
33 #include "perfetto/public/protos/config/trace_config.pzc.h"
34 #include "perfetto/public/protos/trace/interned_data/interned_data.pzc.h"
35 #include "perfetto/public/protos/trace/test_event.pzc.h"
36 #include "perfetto/public/protos/trace/trace.pzc.h"
37 #include "perfetto/public/protos/trace/trace_packet.pzc.h"
38 #include "perfetto/public/protos/trace/track_event/debug_annotation.pzc.h"
39 #include "perfetto/public/protos/trace/track_event/track_descriptor.pzc.h"
40 #include "perfetto/public/protos/trace/track_event/track_event.pzc.h"
41 #include "perfetto/public/protos/trace/trigger.pzc.h"
42 #include "perfetto/public/te_category_macros.h"
43 #include "perfetto/public/te_macros.h"
44 #include "perfetto/public/track_event.h"
45 #include "trace_categories.h"
46 #include "utils.h"
47
48 #include "protos/perfetto/trace/trace.pb.h"
49 #include "protos/perfetto/trace/trace_packet.pb.h"
50 #include "protos/perfetto/trace/interned_data/interned_data.pb.h"
51
52 #include <fstream>
53 #include <iterator>
54 namespace tracing_perfetto {
55
56 using ::perfetto::protos::Trace;
57 using ::perfetto::protos::TracePacket;
58 using ::perfetto::protos::EventCategory;
59 using ::perfetto::protos::EventName;
60 using ::perfetto::protos::FtraceEvent;
61 using ::perfetto::protos::FtraceEventBundle;
62 using ::perfetto::protos::InternedData;
63
64 using ::perfetto::shlib::test_utils::TracingSession;
65
66 const auto PERFETTO_SDK_TRACING = ACONFIG_FLAG(android::os, perfetto_sdk_tracing);
67
68 // TODO(b/303199244): Add tests for all the library functions.
69 class TracingPerfettoTest : public testing::Test {
70 protected:
SetUp()71 void SetUp() override {
72 tracing_perfetto::registerWithPerfetto(false /* test */);
73 }
74 };
75
stopSession(TracingSession & tracing_session)76 Trace stopSession(TracingSession& tracing_session) {
77 tracing_session.FlushBlocking(5000);
78 tracing_session.StopBlocking();
79 std::vector<uint8_t> data = tracing_session.ReadBlocking();
80 std::string data_string(data.begin(), data.end());
81
82 perfetto::protos::Trace trace;
83 trace.ParseFromString(data_string);
84
85 return trace;
86 }
87
verifyTrackEvent(const Trace & trace,const std::string expected_category,const std::string & expected_name)88 void verifyTrackEvent(const Trace& trace, const std::string expected_category,
89 const std::string& expected_name) {
90 bool found = false;
91 for (const TracePacket& packet: trace.packet()) {
92 if (packet.has_track_event() && packet.has_interned_data()) {
93
94 const InternedData& interned_data = packet.interned_data();
95 if (interned_data.event_categories_size() > 0) {
96 const EventCategory& event_category = packet.interned_data().event_categories(0);
97 if (event_category.name() == expected_category) {
98 found = true;
99 }
100 }
101
102 if (interned_data.event_names_size() > 0) {
103 const EventName& event_name = packet.interned_data().event_names(0);
104 if (event_name.name() == expected_name) {
105 found &= true;
106 }
107 }
108
109 if (found) {
110 break;
111 }
112 }
113 }
114 EXPECT_TRUE(found);
115 }
116
verifyAtraceEvent(const Trace & trace,const std::string & expected_name)117 void verifyAtraceEvent(const Trace& trace, const std::string& expected_name) {
118 std::string expected_print_buf = "I|" + std::to_string(gettid()) + "|" + expected_name + "\n";
119
120 bool found = false;
121 for (const TracePacket& packet: trace.packet()) {
122 if (packet.has_ftrace_events()) {
123 const FtraceEventBundle& ftrace_events_bundle = packet.ftrace_events();
124
125 if (ftrace_events_bundle.event_size() > 0) {
126 const FtraceEvent& ftrace_event = ftrace_events_bundle.event(0);
127 if (ftrace_event.has_print() && (ftrace_event.print().buf() == expected_print_buf)) {
128 found = true;
129 break;
130 }
131 }
132 }
133 }
134 EXPECT_TRUE(found);
135 }
136
TEST_F_WITH_FLAGS(TracingPerfettoTest,traceInstantWithPerfetto,REQUIRES_FLAGS_ENABLED (PERFETTO_SDK_TRACING))137 TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfetto,
138 REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
139 std::string event_category = "input";
140 std::string event_name = "traceInstantWithPerfetto";
141
142 TracingSession tracing_session =
143 TracingSession::Builder().add_enabled_category(event_category).Build();
144
145 tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
146
147 Trace trace = stopSession(tracing_session);
148
149 verifyTrackEvent(trace, event_category, event_name);
150 }
151
TEST_F_WITH_FLAGS(TracingPerfettoTest,traceInstantWithAtrace,REQUIRES_FLAGS_ENABLED (PERFETTO_SDK_TRACING))152 TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithAtrace,
153 REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
154 std::string event_category = "input";
155 std::string event_name = "traceInstantWithAtrace";
156
157 TracingSession tracing_session =
158 TracingSession::Builder().add_atrace_category(event_category).Build();
159
160 tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
161
162 Trace trace = stopSession(tracing_session);
163
164 verifyAtraceEvent(trace, event_name);
165 }
166
TEST_F_WITH_FLAGS(TracingPerfettoTest,traceInstantWithPerfettoAndAtrace,REQUIRES_FLAGS_ENABLED (PERFETTO_SDK_TRACING))167 TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtrace,
168 REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
169 std::string event_category = "input";
170 std::string event_name = "traceInstantWithPerfettoAndAtrace";
171
172 TracingSession tracing_session =
173 TracingSession::Builder()
174 .add_atrace_category(event_category)
175 .add_enabled_category(event_category).Build();
176
177 tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
178
179 Trace trace = stopSession(tracing_session);
180
181 verifyAtraceEvent(trace, event_name);
182 }
183
TEST_F_WITH_FLAGS(TracingPerfettoTest,traceInstantWithPerfettoAndAtraceAndPreferTrackEvent,REQUIRES_FLAGS_ENABLED (PERFETTO_SDK_TRACING))184 TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceAndPreferTrackEvent,
185 REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
186 std::string event_category = "input";
187 std::string event_name = "traceInstantWithPerfettoAndAtraceAndPreferTrackEvent";
188
189 TracingSession tracing_session =
190 TracingSession::Builder()
191 .add_atrace_category(event_category)
192 .add_atrace_category_prefer_sdk(event_category)
193 .add_enabled_category(event_category).Build();
194
195 tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
196
197 Trace trace = stopSession(tracing_session);
198
199 verifyTrackEvent(trace, event_category, event_name);
200 }
201
TEST_F_WITH_FLAGS(TracingPerfettoTest,traceInstantWithPerfettoAndAtraceConcurrently,REQUIRES_FLAGS_ENABLED (PERFETTO_SDK_TRACING))202 TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceConcurrently,
203 REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
204 std::string event_category = "input";
205 std::string event_name = "traceInstantWithPerfettoAndAtraceConcurrently";
206
207 TracingSession perfetto_tracing_session =
208 TracingSession::Builder()
209 .add_atrace_category(event_category)
210 .add_atrace_category_prefer_sdk(event_category)
211 .add_enabled_category(event_category).Build();
212
213 TracingSession atrace_tracing_session =
214 TracingSession::Builder()
215 .add_atrace_category(event_category)
216 .add_enabled_category(event_category).Build();
217
218 tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
219
220 Trace atrace_trace = stopSession(atrace_tracing_session);
221 Trace perfetto_trace = stopSession(perfetto_tracing_session);
222
223 verifyAtraceEvent(atrace_trace, event_name);
224 verifyAtraceEvent(perfetto_trace, event_name);
225 }
226 } // namespace tracing_perfetto
227