1 /*
2 * Copyright (C) 2021 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/tracing/traced_proto.h"
18
19 #include "perfetto/test/traced_value_test_support.h"
20 #include "perfetto/tracing/track_event.h"
21 #include "protos/perfetto/trace/test_event.gen.h"
22 #include "protos/perfetto/trace/test_event.pb.h"
23 #include "protos/perfetto/trace/test_event.pbzero.h"
24 #include "protos/perfetto/trace/track_event/track_event.gen.h"
25 #include "protos/perfetto/trace/track_event/track_event.pb.h"
26 #include "test/gtest_and_gmock.h"
27
28 namespace perfetto {
29
30 class TracedProtoTest : public ::testing::Test {
31 public:
TracedProtoTest()32 TracedProtoTest() : context_(track_event_.get(), &incremental_state_) {}
33
context()34 EventContext& context() { return context_; }
35
36 private:
37 protozero::HeapBuffered<protos::pbzero::TrackEvent> track_event_;
38 internal::TrackEventIncrementalState incremental_state_;
39 EventContext context_;
40 };
41
42 using TestPayload = protos::pbzero::TestEvent::TestPayload;
43
TEST_F(TracedProtoTest,SingleInt_WriteField)44 TEST_F(TracedProtoTest, SingleInt_WriteField) {
45 protozero::HeapBuffered<TestPayload> event;
46 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
47 WriteTracedProtoField(proto, TestPayload::kSingleInt, 42);
48
49 protos::TestEvent::TestPayload result;
50 result.ParseFromString(event.SerializeAsString());
51 EXPECT_TRUE(result.has_single_int());
52 EXPECT_EQ(result.single_int(), 42);
53 }
54
TEST_F(TracedProtoTest,SingleInt_Set)55 TEST_F(TracedProtoTest, SingleInt_Set) {
56 protozero::HeapBuffered<TestPayload> event;
57 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
58 proto.Set(TestPayload::kSingleInt, 42);
59
60 protos::TestEvent::TestPayload result;
61 result.ParseFromString(event.SerializeAsString());
62 EXPECT_TRUE(result.has_single_int());
63 EXPECT_EQ(result.single_int(), 42);
64 }
65
TEST_F(TracedProtoTest,RepeatedInt_WriteField)66 TEST_F(TracedProtoTest, RepeatedInt_WriteField) {
67 protozero::HeapBuffered<TestPayload> event;
68 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
69 WriteTracedProtoField(proto, TestPayload::kRepeatedInts,
70 std::vector<int>{1, 2, 3});
71
72 protos::TestEvent::TestPayload result;
73 result.ParseFromString(event.SerializeAsString());
74 EXPECT_THAT(result.repeated_ints(), ::testing::ElementsAre(1, 2, 3));
75 }
76
TEST_F(TracedProtoTest,RepeatedInt_AppendValue)77 TEST_F(TracedProtoTest, RepeatedInt_AppendValue) {
78 protozero::HeapBuffered<TestPayload> event;
79 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
80 proto.AppendValue(TestPayload::kRepeatedInts, 1);
81
82 protos::TestEvent::TestPayload result;
83 result.ParseFromString(event.SerializeAsString());
84 EXPECT_THAT(result.repeated_ints(), ::testing::ElementsAre(1));
85 }
86
TEST_F(TracedProtoTest,RepeatedInt_AppendFrom)87 TEST_F(TracedProtoTest, RepeatedInt_AppendFrom) {
88 protozero::HeapBuffered<TestPayload> event;
89 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
90 proto.AppendFrom(TestPayload::kRepeatedInts, std::vector<int>{1, 2, 3});
91
92 protos::TestEvent::TestPayload result;
93 result.ParseFromString(event.SerializeAsString());
94 EXPECT_THAT(result.repeated_ints(), ::testing::ElementsAre(1, 2, 3));
95 }
96
TEST_F(TracedProtoTest,SingleString_WriteField)97 TEST_F(TracedProtoTest, SingleString_WriteField) {
98 protozero::HeapBuffered<TestPayload> event;
99 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
100 WriteTracedProtoField(proto, TestPayload::kSingleString, "foo");
101
102 protos::TestEvent::TestPayload result;
103 result.ParseFromString(event.SerializeAsString());
104 EXPECT_TRUE(result.has_single_string());
105 EXPECT_EQ(result.single_string(), "foo");
106 }
107
TEST_F(TracedProtoTest,SingleString_Set)108 TEST_F(TracedProtoTest, SingleString_Set) {
109 protozero::HeapBuffered<TestPayload> event;
110 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
111 proto.Set(TestPayload::kSingleString, "foo");
112
113 protos::TestEvent::TestPayload result;
114 result.ParseFromString(event.SerializeAsString());
115 EXPECT_TRUE(result.has_single_string());
116 EXPECT_EQ(result.single_string(), "foo");
117 }
118
TEST_F(TracedProtoTest,RepeatedString_WriteField)119 TEST_F(TracedProtoTest, RepeatedString_WriteField) {
120 protozero::HeapBuffered<TestPayload> event;
121 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
122 WriteTracedProtoField(proto, TestPayload::kStr,
123 std::vector<std::string>{"foo", "bar"});
124
125 protos::TestEvent::TestPayload result;
126 result.ParseFromString(event.SerializeAsString());
127 EXPECT_THAT(result.str(), ::testing::ElementsAre("foo", "bar"));
128 }
129
TEST_F(TracedProtoTest,RepeatedString_AppendFrom)130 TEST_F(TracedProtoTest, RepeatedString_AppendFrom) {
131 protozero::HeapBuffered<TestPayload> event;
132 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
133 proto.AppendFrom(TestPayload::kStr, std::vector<std::string>{"foo", "bar"});
134
135 protos::TestEvent::TestPayload result;
136 result.ParseFromString(event.SerializeAsString());
137 EXPECT_THAT(result.str(), ::testing::ElementsAre("foo", "bar"));
138 }
139
TEST_F(TracedProtoTest,RepeatedString_AppendValue)140 TEST_F(TracedProtoTest, RepeatedString_AppendValue) {
141 protozero::HeapBuffered<TestPayload> event;
142 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
143 proto.AppendValue(TestPayload::kStr, "foo");
144
145 protos::TestEvent::TestPayload result;
146 result.ParseFromString(event.SerializeAsString());
147 EXPECT_THAT(result.str(), ::testing::ElementsAre("foo"));
148 }
149
150 namespace {
151
152 struct Foo {
WriteIntoTraceperfetto::__anone69dc3860111::Foo153 void WriteIntoTrace(TracedProto<TestPayload> message) const {
154 message->set_single_int(42);
155
156 auto dict = std::move(message).AddDebugAnnotations();
157 dict.Add("arg", "value");
158 }
159 };
160
161 struct Bar {};
162
163 } // namespace
164
165 template <>
166 struct TraceFormatTraits<Bar> {
WriteIntoTraceperfetto::TraceFormatTraits167 static void WriteIntoTrace(
168 TracedProto<protos::pbzero::TestEvent::TestPayload> message,
169 const Bar&) {
170 message->set_single_string("value");
171 }
172 };
173
TEST_F(TracedProtoTest,SingleNestedMessage_Method)174 TEST_F(TracedProtoTest, SingleNestedMessage_Method) {
175 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
176 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
177 context().Wrap(event.get());
178 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, Foo());
179
180 protos::TestEvent result;
181 result.ParseFromString(event.SerializeAsString());
182 EXPECT_EQ(result.payload().single_int(), 42);
183 }
184
TEST_F(TracedProtoTest,SingleNestedMessage_TraceFormatTraits)185 TEST_F(TracedProtoTest, SingleNestedMessage_TraceFormatTraits) {
186 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
187 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
188 context().Wrap(event.get());
189 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, Bar());
190
191 protos::TestEvent result;
192 result.ParseFromString(event.SerializeAsString());
193 EXPECT_EQ(result.payload().single_string(), "value");
194 }
195
TEST_F(TracedProtoTest,SingleNestedMessage_Pointer)196 TEST_F(TracedProtoTest, SingleNestedMessage_Pointer) {
197 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
198 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
199 context().Wrap(event.get());
200 Bar bar;
201 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, &bar);
202
203 protos::TestEvent result;
204 result.ParseFromString(event.SerializeAsString());
205 EXPECT_EQ(result.payload().single_string(), "value");
206 }
207
TEST_F(TracedProtoTest,SingleNestedMessage_UniquePtr)208 TEST_F(TracedProtoTest, SingleNestedMessage_UniquePtr) {
209 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
210 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
211 context().Wrap(event.get());
212 std::unique_ptr<Bar> bar(new Bar);
213 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, bar);
214
215 protos::TestEvent result;
216 result.ParseFromString(event.SerializeAsString());
217 EXPECT_EQ(result.payload().single_string(), "value");
218 }
219
TEST_F(TracedProtoTest,SingleNestedMessage_EmptyUniquePtr)220 TEST_F(TracedProtoTest, SingleNestedMessage_EmptyUniquePtr) {
221 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
222 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
223 context().Wrap(event.get());
224 std::unique_ptr<Bar> bar;
225 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, bar);
226
227 protos::TestEvent result;
228 result.ParseFromString(event.SerializeAsString());
229 EXPECT_FALSE(result.payload().has_single_string());
230 }
231
TEST_F(TracedProtoTest,SingleNestedMessage_Nullptr)232 TEST_F(TracedProtoTest, SingleNestedMessage_Nullptr) {
233 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
234 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
235 context().Wrap(event.get());
236 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, nullptr);
237
238 protos::TestEvent result;
239 result.ParseFromString(event.SerializeAsString());
240 EXPECT_FALSE(result.payload().has_single_string());
241 }
242
TEST_F(TracedProtoTest,SingleNestedMessage_Method_Set)243 TEST_F(TracedProtoTest, SingleNestedMessage_Method_Set) {
244 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
245 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
246 context().Wrap(event.get());
247 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, Foo());
248
249 protos::TestEvent result;
250 result.ParseFromString(event.SerializeAsString());
251 EXPECT_EQ(result.payload().single_int(), 42);
252 }
253
TEST_F(TracedProtoTest,SingleNestedMessage_TraceFormatTraits_Set)254 TEST_F(TracedProtoTest, SingleNestedMessage_TraceFormatTraits_Set) {
255 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
256 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
257 context().Wrap(event.get());
258 proto.Set(protos::pbzero::TestEvent::kPayload, Bar());
259
260 protos::TestEvent result;
261 result.ParseFromString(event.SerializeAsString());
262 EXPECT_EQ(result.payload().single_string(), "value");
263 }
264
TEST_F(TracedProtoTest,SingleNestedMessage_Pointer_Set)265 TEST_F(TracedProtoTest, SingleNestedMessage_Pointer_Set) {
266 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
267 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
268 context().Wrap(event.get());
269 Bar bar;
270 proto.Set(protos::pbzero::TestEvent::kPayload, &bar);
271
272 protos::TestEvent result;
273 result.ParseFromString(event.SerializeAsString());
274 EXPECT_EQ(result.payload().single_string(), "value");
275 }
276
TEST_F(TracedProtoTest,SingleNestedMessage_UniquePtr_Set)277 TEST_F(TracedProtoTest, SingleNestedMessage_UniquePtr_Set) {
278 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
279 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
280 context().Wrap(event.get());
281 std::unique_ptr<Bar> bar(new Bar);
282 proto.Set(protos::pbzero::TestEvent::kPayload, bar);
283
284 protos::TestEvent result;
285 result.ParseFromString(event.SerializeAsString());
286 EXPECT_EQ(result.payload().single_string(), "value");
287 }
288
TEST_F(TracedProtoTest,SingleNestedMessage_EmptyUniquePtr_Set)289 TEST_F(TracedProtoTest, SingleNestedMessage_EmptyUniquePtr_Set) {
290 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
291 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
292 context().Wrap(event.get());
293 std::unique_ptr<Bar> bar;
294 proto.Set(protos::pbzero::TestEvent::kPayload, bar);
295
296 protos::TestEvent result;
297 result.ParseFromString(event.SerializeAsString());
298 EXPECT_FALSE(result.payload().has_single_string());
299 }
300
TEST_F(TracedProtoTest,SingleNestedMessage_Nullptr_Set)301 TEST_F(TracedProtoTest, SingleNestedMessage_Nullptr_Set) {
302 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
303 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
304 context().Wrap(event.get());
305 proto.Set(protos::pbzero::TestEvent::kPayload, nullptr);
306
307 protos::TestEvent result;
308 result.ParseFromString(event.SerializeAsString());
309 EXPECT_FALSE(result.payload().has_single_string());
310 }
311
TEST_F(TracedProtoTest,RepeatedNestedMessage_Method)312 TEST_F(TracedProtoTest, RepeatedNestedMessage_Method) {
313 protozero::HeapBuffered<TestPayload> event;
314 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
315 WriteTracedProtoField(proto, TestPayload::kNested,
316 std::vector<Foo>{Foo(), Foo()});
317
318 protos::TestEvent::TestPayload result;
319 result.ParseFromString(event.SerializeAsString());
320 EXPECT_EQ(result.nested_size(), 2);
321 EXPECT_EQ(result.nested(0).single_int(), 42);
322 EXPECT_EQ(result.nested(1).single_int(), 42);
323 }
324
TEST_F(TracedProtoTest,RepeatedNestedMessage_TraceFormatTraits)325 TEST_F(TracedProtoTest, RepeatedNestedMessage_TraceFormatTraits) {
326 protozero::HeapBuffered<TestPayload> event;
327 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
328 WriteTracedProtoField(proto, TestPayload::kNested,
329 std::vector<Bar>{Bar(), Bar()});
330
331 protos::TestEvent::TestPayload result;
332 result.ParseFromString(event.SerializeAsString());
333 EXPECT_EQ(result.nested_size(), 2);
334 EXPECT_EQ(result.nested(0).single_string(), "value");
335 EXPECT_EQ(result.nested(1).single_string(), "value");
336 }
337
TEST_F(TracedProtoTest,RepeatedNestedMessage_Pointer)338 TEST_F(TracedProtoTest, RepeatedNestedMessage_Pointer) {
339 protozero::HeapBuffered<TestPayload> event;
340 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
341 Bar bar;
342 std::vector<Bar*> bars;
343 bars.push_back(&bar);
344 bars.push_back(nullptr);
345 WriteTracedProtoField(proto, TestPayload::kNested, bars);
346
347 protos::TestEvent::TestPayload result;
348 result.ParseFromString(event.SerializeAsString());
349 EXPECT_EQ(result.nested_size(), 2);
350 EXPECT_EQ(result.nested(0).single_string(), "value");
351 EXPECT_FALSE(result.nested(1).has_single_string());
352 }
353
TEST_F(TracedProtoTest,RepeatedNestedMessage_Method_AppendValue)354 TEST_F(TracedProtoTest, RepeatedNestedMessage_Method_AppendValue) {
355 protozero::HeapBuffered<TestPayload> event;
356 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
357 proto.AppendValue(TestPayload::kNested, Foo());
358
359 protos::TestEvent::TestPayload result;
360 result.ParseFromString(event.SerializeAsString());
361 EXPECT_EQ(result.nested_size(), 1);
362 EXPECT_EQ(result.nested(0).single_int(), 42);
363 }
364
TEST_F(TracedProtoTest,RepeatedNestedMessage_TraceFormatTraits_AppendValue)365 TEST_F(TracedProtoTest, RepeatedNestedMessage_TraceFormatTraits_AppendValue) {
366 protozero::HeapBuffered<TestPayload> event;
367 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
368 proto.AppendValue(TestPayload::kNested, Bar());
369
370 protos::TestEvent::TestPayload result;
371 result.ParseFromString(event.SerializeAsString());
372 EXPECT_EQ(result.nested_size(), 1);
373 EXPECT_EQ(result.nested(0).single_string(), "value");
374 }
375
TEST_F(TracedProtoTest,RepeatedNestedMessage_Pointer_AppendValue)376 TEST_F(TracedProtoTest, RepeatedNestedMessage_Pointer_AppendValue) {
377 protozero::HeapBuffered<TestPayload> event;
378 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
379 Bar bar;
380 proto.AppendValue(TestPayload::kNested, &bar);
381 proto.AppendValue(TestPayload::kNested, nullptr);
382
383 protos::TestEvent::TestPayload result;
384 result.ParseFromString(event.SerializeAsString());
385 EXPECT_EQ(result.nested_size(), 2);
386 EXPECT_EQ(result.nested(0).single_string(), "value");
387 EXPECT_FALSE(result.nested(1).has_single_string());
388 }
389
TEST_F(TracedProtoTest,RepeatedNestedMessage_Method_AppendFrom)390 TEST_F(TracedProtoTest, RepeatedNestedMessage_Method_AppendFrom) {
391 protozero::HeapBuffered<TestPayload> event;
392 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
393 proto.AppendFrom(TestPayload::kNested, std::vector<Foo>{Foo(), Foo()});
394
395 protos::TestEvent::TestPayload result;
396 result.ParseFromString(event.SerializeAsString());
397 EXPECT_EQ(result.nested_size(), 2);
398 EXPECT_EQ(result.nested(0).single_int(), 42);
399 EXPECT_EQ(result.nested(1).single_int(), 42);
400 }
401
TEST_F(TracedProtoTest,RepeatedNestedMessage_TraceFormatTraits_AppendFrom)402 TEST_F(TracedProtoTest, RepeatedNestedMessage_TraceFormatTraits_AppendFrom) {
403 protozero::HeapBuffered<TestPayload> event;
404 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
405 proto.AppendFrom(TestPayload::kNested, std::vector<Bar>{Bar(), Bar()});
406
407 protos::TestEvent::TestPayload result;
408 result.ParseFromString(event.SerializeAsString());
409 EXPECT_EQ(result.nested_size(), 2);
410 EXPECT_EQ(result.nested(0).single_string(), "value");
411 EXPECT_EQ(result.nested(1).single_string(), "value");
412 }
413
TEST_F(TracedProtoTest,RepeatedNestedMessage_Pointer_AppendFrom)414 TEST_F(TracedProtoTest, RepeatedNestedMessage_Pointer_AppendFrom) {
415 protozero::HeapBuffered<TestPayload> event;
416 perfetto::TracedProto<TestPayload> proto = context().Wrap(event.get());
417 Bar bar;
418 std::vector<Bar*> bars;
419 bars.push_back(&bar);
420 bars.push_back(nullptr);
421 proto.AppendFrom(TestPayload::kNested, bars);
422
423 protos::TestEvent::TestPayload result;
424 result.ParseFromString(event.SerializeAsString());
425 EXPECT_EQ(result.nested_size(), 2);
426 EXPECT_EQ(result.nested(0).single_string(), "value");
427 EXPECT_FALSE(result.nested(1).has_single_string());
428 }
429
TEST_F(TracedProtoTest,WriteDebugAnnotations)430 TEST_F(TracedProtoTest, WriteDebugAnnotations) {
431 protozero::HeapBuffered<protos::pbzero::TestEvent> event;
432 perfetto::TracedProto<protos::pbzero::TestEvent> proto =
433 context().Wrap(event.get());
434 WriteTracedProtoField(proto, protos::pbzero::TestEvent::kPayload, Foo());
435
436 protos::TestEvent result;
437 result.ParseFromString(event.SerializeAsString());
438
439 protos::DebugAnnotation dict;
440 for (const auto& annotation : result.payload().debug_annotations()) {
441 *dict.add_dict_entries() = annotation;
442 }
443
444 EXPECT_EQ(internal::DebugAnnotationToString(dict.SerializeAsString()),
445 "{arg:value}");
446 }
447
448 } // namespace perfetto
449