xref: /aosp_15_r20/external/perfetto/src/tracing/traced_proto_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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