• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "src/trace_processor/util/protozero_to_json.h"
18 
19 #include "perfetto/ext/base/string_utils.h"
20 #include "perfetto/protozero/scattered_heap_buffer.h"
21 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
22 #include "src/trace_processor/importers/proto/track_event.descriptor.h"
23 #include "src/trace_processor/test_messages.descriptor.h"
24 #include "src/trace_processor/util/descriptors.h"
25 #include "test/gtest_and_gmock.h"
26 
27 #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
28 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
29 
30 #if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
31 #include "protos/perfetto/metrics/chrome/all_chrome_metrics.pb.h"  // nogncheck
32 #include "src/trace_processor/metrics/all_chrome_metrics.descriptor.h"  // nogncheck
33 #endif
34 
35 namespace perfetto {
36 namespace trace_processor {
37 namespace protozero_to_json {
38 
39 namespace {
40 
41 constexpr size_t kChunkSize = 42;
42 
43 using ::protozero::test::protos::pbzero::EveryField;
44 using ::protozero::test::protos::pbzero::PackedRepeatedFields;
45 using ::testing::_;
46 using ::testing::ElementsAre;
47 using ::testing::Eq;
48 using ::testing::StartsWith;
49 
TEST(ProtozeroToJsonTest,CustomDescriptorPoolEmpty)50 TEST(ProtozeroToJsonTest, CustomDescriptorPoolEmpty) {
51   using perfetto::protos::pbzero::TrackEvent;
52   protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
53   auto binary_proto = msg.SerializeAsArray();
54   DescriptorPool pool;
55   auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
56                                               kTrackEventDescriptor.size());
57   ASSERT_TRUE(status.ok());
58   EXPECT_EQ("{}", ProtozeroToJson(pool, ".perfetto.protos.TrackEvent",
59                                   binary_proto, kPretty));
60   EXPECT_EQ("{}", ProtozeroToJson(pool, ".perfetto.protos.TrackEvent",
61                                   binary_proto, kNone));
62 }
63 
TEST(ProtozeroToJsonTest,CustomDescriptorPoolBasic)64 TEST(ProtozeroToJsonTest, CustomDescriptorPoolBasic) {
65   using perfetto::protos::pbzero::TrackEvent;
66   protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
67   msg->set_track_uuid(4);
68   msg->set_timestamp_delta_us(3);
69   auto binary_proto = msg.SerializeAsArray();
70   DescriptorPool pool;
71   auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
72                                               kTrackEventDescriptor.size());
73   ASSERT_TRUE(status.ok());
74   EXPECT_EQ(R"({
75   "track_uuid": 4,
76   "timestamp_delta_us": 3
77 })",
78             ProtozeroToJson(pool, ".perfetto.protos.TrackEvent", binary_proto,
79                             kPretty));
80   EXPECT_EQ(R"({"track_uuid":4,"timestamp_delta_us":3})",
81             ProtozeroToJson(pool, ".perfetto.protos.TrackEvent", binary_proto,
82                             kNone));
83 }
84 
TEST(ProtozeroToJsonTest,CustomDescriptorPoolNestedMsg)85 TEST(ProtozeroToJsonTest, CustomDescriptorPoolNestedMsg) {
86   using perfetto::protos::pbzero::TrackEvent;
87   protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
88   msg->set_track_uuid(4);
89   auto* state = msg->set_cc_scheduler_state();
90   state->set_deadline_us(7);
91   auto* machine = state->set_state_machine();
92   auto* minor_state = machine->set_minor_state();
93   minor_state->set_commit_count(8);
94   state->set_observing_begin_frame_source(true);
95   msg->set_timestamp_delta_us(3);
96   auto binary_proto = msg.SerializeAsArray();
97 
98   DescriptorPool pool;
99   auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
100                                               kTrackEventDescriptor.size());
101   ASSERT_TRUE(status.ok());
102 
103   EXPECT_EQ(R"({
104   "track_uuid": 4,
105   "cc_scheduler_state": {
106     "deadline_us": 7,
107     "state_machine": {
108       "minor_state": {
109         "commit_count": 8
110       }
111     },
112     "observing_begin_frame_source": true
113   },
114   "timestamp_delta_us": 3
115 })",
116             ProtozeroToJson(pool, ".perfetto.protos.TrackEvent", binary_proto,
117                             kPretty));
118 
119   EXPECT_EQ(
120       R"({"track_uuid":4,"cc_scheduler_state":{"deadline_us":7,"state_machine":{"minor_state":{"commit_count":8}},"observing_begin_frame_source":true},"timestamp_delta_us":3})",
121       ProtozeroToJson(pool, ".perfetto.protos.TrackEvent", binary_proto,
122                       kNone));
123 }
124 
125 // This test depends on the CustomOptions message in descriptor.proto which
126 // is very tricky to point to on the non-standalone build.
127 #if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
TEST(ProtozeroToJsonTest,CustomDescriptorPoolAnnotations)128 TEST(ProtozeroToJsonTest, CustomDescriptorPoolAnnotations) {
129   using perfetto::protos::TestChromeMetric;
130   TestChromeMetric msg;
131   msg.set_test_value(1);
132   auto binary_proto = msg.SerializeAsString();
133   protozero::ConstBytes binary_proto_bytes{
134       reinterpret_cast<const uint8_t*>(binary_proto.data()),
135       binary_proto.size()};
136 
137   DescriptorPool pool;
138   auto status = pool.AddFromFileDescriptorSet(
139       kAllChromeMetricsDescriptor.data(), kAllChromeMetricsDescriptor.size());
140   ASSERT_TRUE(status.ok());
141 
142   EXPECT_EQ(R"({
143   "test_value": 1,
144   "__annotations": {
145     "test_value": {
146       "__field_options": {
147         "unit": "count_smallerIsBetter"
148       }
149     }
150   }
151 })",
152             ProtozeroToJson(pool, ".perfetto.protos.TestChromeMetric",
153                             binary_proto_bytes, kPretty | kInlineAnnotations));
154 }
155 #endif
156 
157 // Sets up a descriptor pool with all the messages from
158 // "src/protozero/test/example_proto/test_messages.proto"
159 class ProtozeroToJsonTestMessageTest : public testing::Test {
160  protected:
SetUp()161   void SetUp() override {
162     auto status = pool_.AddFromFileDescriptorSet(
163         kTestMessagesDescriptor.data(), kTestMessagesDescriptor.size());
164     ASSERT_TRUE(status.ok());
165   }
166 
167   DescriptorPool pool_;
168 };
169 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntInt32)170 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntInt32) {
171   protozero::HeapBuffered<EveryField> msg;
172   msg->set_field_int32(42);
173 
174   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
175                             msg.SerializeAsArray(), kNone),
176             R"({"field_int32":42})");
177 }
178 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntSint32)179 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntSint32) {
180   protozero::HeapBuffered<EveryField> msg;
181   msg->set_field_sint32(-42);
182 
183   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
184                             msg.SerializeAsArray(), kNone),
185             R"({"field_sint32":-42})");
186 }
187 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntUint32)188 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntUint32) {
189   protozero::HeapBuffered<EveryField> msg;
190   msg->set_field_uint32(3000000000);
191 
192   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
193                             msg.SerializeAsArray(), kNone),
194             R"({"field_uint32":3000000000})");
195 }
196 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntInt64)197 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntInt64) {
198   protozero::HeapBuffered<EveryField> msg;
199   msg->set_field_int64(3000000000);
200 
201   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
202                             msg.SerializeAsArray(), kNone),
203             R"({"field_int64":3000000000})");
204 }
205 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntSint64)206 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntSint64) {
207   protozero::HeapBuffered<EveryField> msg;
208   msg->set_field_sint64(INT64_C(-3000000000));
209 
210   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
211                             msg.SerializeAsArray(), kNone),
212             R"({"field_sint64":-3000000000})");
213 }
214 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntBool)215 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntBool) {
216   protozero::HeapBuffered<EveryField> msg;
217   msg->set_field_bool(true);
218 
219   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
220                             msg.SerializeAsArray(), kNone),
221             R"({"field_bool":true})");
222 }
223 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntSmallEnum)224 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntSmallEnum) {
225   protozero::HeapBuffered<EveryField> msg;
226   msg->set_small_enum(protozero::test::protos::pbzero::TO_BE);
227 
228   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
229                             msg.SerializeAsArray(), kNone),
230             R"({"small_enum":"TO_BE"})");
231 }
232 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntSignedEnum)233 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntSignedEnum) {
234   protozero::HeapBuffered<EveryField> msg;
235   msg->set_signed_enum(protozero::test::protos::pbzero::NEGATIVE);
236 
237   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
238                             msg.SerializeAsArray(), kNone),
239             R"({"signed_enum":"NEGATIVE"})");
240 }
241 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntBigEnum)242 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntBigEnum) {
243   protozero::HeapBuffered<EveryField> msg;
244   msg->set_big_enum(protozero::test::protos::pbzero::END);
245 
246   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
247                             msg.SerializeAsArray(), kNone),
248             R"({"big_enum":"END"})");
249 }
250 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntEnumUnknown)251 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntEnumUnknown) {
252   protozero::HeapBuffered<EveryField> msg;
253   msg->AppendVarInt(EveryField::kSmallEnumFieldNumber, 42);
254   ASSERT_EQ(EveryField::kSmallEnumFieldNumber, 51);
255 
256   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
257                             msg.SerializeAsArray(), kNone),
258             R"({"small_enum":42})");
259 }
260 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntUnknown)261 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntUnknown) {
262   protozero::HeapBuffered<EveryField> msg;
263   msg->AppendVarInt(/*field_id=*/9999, /*value=*/42);
264 
265   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
266                             msg.SerializeAsArray(), kNone),
267             R"({"9999":42})");
268 }
269 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntMismatch)270 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntMismatch) {
271   protozero::HeapBuffered<EveryField> msg;
272   ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
273   msg->AppendVarInt(EveryField::kFieldStringFieldNumber, 42);
274 
275   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
276                             msg.SerializeAsArray(), kNone),
277             R"({"500":42})");
278 }
279 
TEST_F(ProtozeroToJsonTestMessageTest,FieldVarIntForPacked)280 TEST_F(ProtozeroToJsonTestMessageTest, FieldVarIntForPacked) {
281   // Even though field_int32 has [packed = true], it still accepts a non-packed
282   // representation.
283   protozero::HeapBuffered<PackedRepeatedFields> msg;
284   msg->AppendVarInt(PackedRepeatedFields::kFieldInt32FieldNumber, 42);
285 
286   EXPECT_EQ(
287       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
288                       msg.SerializeAsArray(), kNone),
289       R"({"field_int32":[42]})");
290 }
291 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed32Signed)292 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed32Signed) {
293   protozero::HeapBuffered<EveryField> msg;
294   msg->set_field_sfixed32(-42);
295 
296   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
297                             msg.SerializeAsArray(), kNone),
298             R"({"field_sfixed32":-42})");
299 }
300 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed32Unsigned)301 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed32Unsigned) {
302   protozero::HeapBuffered<EveryField> msg;
303   msg->set_field_fixed32(3000000000);
304 
305   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
306                             msg.SerializeAsArray(), kNone),
307             R"({"field_fixed32":3000000000})");
308 }
309 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed32Float)310 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed32Float) {
311   protozero::HeapBuffered<EveryField> msg;
312   msg->set_field_float(24.125);
313 
314   EXPECT_THAT(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
315                               msg.SerializeAsArray(), kNone),
316               StartsWith(R"({"field_float":24.125)"));
317 }
318 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed32Unknown)319 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed32Unknown) {
320   protozero::HeapBuffered<EveryField> msg;
321   msg->AppendFixed<uint32_t>(/*field_id=*/9999, /*value=*/0x1);
322 
323   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
324                             msg.SerializeAsArray(), kNone),
325             R"({"9999":1})");
326 }
327 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed32Mismatch)328 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed32Mismatch) {
329   protozero::HeapBuffered<EveryField> msg;
330   ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
331   msg->AppendFixed<uint32_t>(EveryField::kFieldStringFieldNumber, 0x1);
332 
333   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
334                             msg.SerializeAsArray(), kNone),
335             R"({"500":1})");
336 }
337 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed64Signed)338 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed64Signed) {
339   protozero::HeapBuffered<EveryField> msg;
340   msg->set_field_sfixed64(-42);
341 
342   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
343                             msg.SerializeAsArray(), kNone),
344             R"({"field_sfixed64":-42})");
345 }
346 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed64Unsigned)347 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed64Unsigned) {
348   protozero::HeapBuffered<EveryField> msg;
349   msg->set_field_fixed64(3000000000);
350 
351   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
352                             msg.SerializeAsArray(), kNone),
353             R"({"field_fixed64":3000000000})");
354 }
355 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed64Double)356 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed64Double) {
357   protozero::HeapBuffered<EveryField> msg;
358   msg->set_field_double(24.125);
359 
360   EXPECT_THAT(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
361                               msg.SerializeAsArray(), kNone),
362               StartsWith(R"({"field_double":24.125)"));
363 }
364 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed64Unknown)365 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed64Unknown) {
366   protozero::HeapBuffered<EveryField> msg;
367   msg->AppendFixed<uint64_t>(/*field_id=*/9999, /*value=*/0x1);
368 
369   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
370                             msg.SerializeAsArray(), kNone),
371             R"({"9999":1})");
372 }
373 
TEST_F(ProtozeroToJsonTestMessageTest,FieldFixed64Mismatch)374 TEST_F(ProtozeroToJsonTestMessageTest, FieldFixed64Mismatch) {
375   protozero::HeapBuffered<EveryField> msg;
376   ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
377   msg->AppendFixed<uint64_t>(EveryField::kFieldStringFieldNumber, 0x1);
378 
379   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
380                             msg.SerializeAsArray(), kNone),
381             R"({"500":1})");
382 }
383 
TEST_F(ProtozeroToJsonTestMessageTest,FieldLengthLimitedString)384 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedString) {
385   protozero::HeapBuffered<EveryField> msg;
386   msg->set_field_string("Hello");
387 
388   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
389                             msg.SerializeAsArray(), kNone),
390             R"({"field_string":"Hello"})");
391 }
392 
TEST_F(ProtozeroToJsonTestMessageTest,FieldLengthLimitedBadString)393 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedBadString) {
394   protozero::HeapBuffered<EveryField> msg;
395   msg->set_field_string(R"("\
396 )");
397   std::string res = R"({"field_string":"\"\\\n"})";
398   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
399                             msg.SerializeAsArray(), kNone),
400             res);
401 }
402 
403 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedUnicodeString) {
404   protozero::HeapBuffered<EveryField> msg;
405   msg->set_field_string(R"($£Иह€한��)");
406   std::string res =
407       R"({"field_string":"$\u00a3\u0418\u0939\u20ac\ud55c\ud800\udf48"})";
408   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
409                             msg.SerializeAsArray(), kNone),
410             res);
411 }
412 
413 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedBytes) {
414   protozero::HeapBuffered<EveryField> msg;
415   msg->set_field_bytes("Hello");
416 
417   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
418                             msg.SerializeAsArray(), kNone),
419             R"({"field_bytes":"Hello"})");
420 }
421 
422 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedUnknown) {
423   protozero::HeapBuffered<EveryField> msg;
424   msg->AppendString(9999, "Hello");
425 
426   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
427                             msg.SerializeAsArray(), kNone),
428             R"({"9999":"Hello"})");
429 }
430 
431 TEST_F(ProtozeroToJsonTestMessageTest, RepeatedInt32) {
432   protozero::HeapBuffered<EveryField> msg;
433   msg->add_repeated_int32(-42);
434   msg->add_repeated_int32(2147483647);
435   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
436                             msg.SerializeAsArray(), kNone),
437             R"({"repeated_int32":[-42,2147483647]})");
438 }
439 
440 TEST_F(ProtozeroToJsonTestMessageTest, RepeatedFixed64) {
441   protozero::HeapBuffered<EveryField> msg;
442   msg->add_repeated_fixed64(42);
443   msg->add_repeated_fixed64(2147483647);
444   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
445                             msg.SerializeAsArray(), kNone),
446             R"({"repeated_fixed64":[42,2147483647]})");
447 }
448 
449 TEST_F(ProtozeroToJsonTestMessageTest, RepeatedSignedFixed32) {
450   protozero::HeapBuffered<EveryField> msg;
451   msg->add_repeated_sfixed32(-42);
452   msg->add_repeated_sfixed32(2147483647);
453   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
454                             msg.SerializeAsArray(), kNone),
455             R"({"repeated_sfixed32":[-42,2147483647]})");
456 }
457 
458 TEST_F(ProtozeroToJsonTestMessageTest, RepeatedString) {
459   protozero::HeapBuffered<EveryField> msg;
460   msg->add_repeated_string("Hello");
461   msg->add_repeated_string("world!");
462   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
463                             msg.SerializeAsArray(), kNone),
464             R"({"repeated_string":["Hello","world!"]})");
465 }
466 
467 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedBool) {
468   protozero::HeapBuffered<EveryField> msg;
469   protozero::PackedVarInt buf;
470   buf.Append<int32_t>(1);
471   buf.Append<int32_t>(0);
472   buf.Append<int32_t>(1);
473   msg->AppendBytes(EveryField::kFieldBoolFieldNumber, buf.data(), buf.size());
474   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
475                             msg.SerializeAsArray(), kNone),
476             R"({"field_bool":[true,false,true]})");
477 }
478 
479 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedForNonPacked) {
480   // Even though repeated_int32 doesn't have [packed = true], it still accepts a
481   // packed representation.
482   protozero::HeapBuffered<EveryField> msg;
483   protozero::PackedVarInt buf;
484   buf.Append<int32_t>(-42);
485   buf.Append<int32_t>(2147483647);
486   msg->AppendBytes(EveryField::kRepeatedInt32FieldNumber, buf.data(),
487                    buf.size());
488 
489   EXPECT_EQ(ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
490                             msg.SerializeAsArray(), kNone),
491             R"({"repeated_int32":[-42,2147483647]})");
492 }
493 
494 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntInt32) {
495   protozero::HeapBuffered<PackedRepeatedFields> msg;
496   protozero::PackedVarInt buf;
497   buf.Append<int32_t>(-42);
498   buf.Append<int32_t>(2147483647);
499   msg->set_field_int32(buf);
500 
501   EXPECT_EQ(
502       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
503                       msg.SerializeAsArray(), kNone),
504       R"({"field_int32":[-42,2147483647]})");
505 }
506 
507 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntInt64) {
508   protozero::HeapBuffered<PackedRepeatedFields> msg;
509   protozero::PackedVarInt buf;
510   buf.Append<int64_t>(-42);
511   buf.Append<int64_t>(3000000000);
512   msg->set_field_int64(buf);
513 
514   EXPECT_EQ(
515       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
516                       msg.SerializeAsArray(), kNone),
517       R"({"field_int64":[-42,3000000000]})");
518 }
519 
520 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntUint32) {
521   protozero::HeapBuffered<PackedRepeatedFields> msg;
522   protozero::PackedVarInt buf;
523   buf.Append<uint32_t>(42);
524   buf.Append<uint32_t>(3000000000);
525   msg->set_field_uint32(buf);
526 
527   EXPECT_EQ(
528       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
529                       msg.SerializeAsArray(), kNone),
530       R"({"field_uint32":[42,3000000000]})");
531 }
532 
533 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntUint64) {
534   protozero::HeapBuffered<PackedRepeatedFields> msg;
535   protozero::PackedVarInt buf;
536   buf.Append<uint64_t>(42);
537   buf.Append<uint64_t>(3000000000000);
538   msg->set_field_uint64(buf);
539 
540   EXPECT_EQ(
541       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
542                       msg.SerializeAsArray(), kNone),
543       R"({"field_uint64":[42,3000000000000]})");
544 }
545 
546 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed32Uint32) {
547   protozero::HeapBuffered<PackedRepeatedFields> msg;
548   protozero::PackedFixedSizeInt<uint32_t> buf;
549   buf.Append(42);
550   buf.Append(3000000000);
551   msg->set_field_fixed32(buf);
552 
553   EXPECT_EQ(
554       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
555                       msg.SerializeAsArray(), kNone),
556       R"({"field_fixed32":[42,3000000000]})");
557 }
558 
559 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed32Int32) {
560   protozero::HeapBuffered<PackedRepeatedFields> msg;
561   protozero::PackedFixedSizeInt<int32_t> buf;
562   buf.Append(-42);
563   buf.Append(42);
564   msg->set_field_sfixed32(buf);
565 
566   EXPECT_EQ(
567       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
568                       msg.SerializeAsArray(), kNone),
569       R"({"field_sfixed32":[-42,42]})");
570 }
571 
572 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed32Float) {
573   protozero::HeapBuffered<PackedRepeatedFields> msg;
574   protozero::PackedFixedSizeInt<float> buf;
575   buf.Append(-42);
576   buf.Append(42.125);
577   msg->set_field_float(buf);
578 
579   std::string output =
580       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
581                       msg.SerializeAsArray(), kPretty);
582 
583   EXPECT_THAT(base::SplitString(output, "\n"),
584               ElementsAre("{", R"(  "field_float": [)", StartsWith("    -42"),
585                           StartsWith("    42.125"), R"(  ])", R"(})"));
586 }
587 
588 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed64Uint64) {
589   protozero::HeapBuffered<PackedRepeatedFields> msg;
590   protozero::PackedFixedSizeInt<uint64_t> buf;
591   buf.Append(42);
592   buf.Append(3000000000000);
593   msg->set_field_fixed64(buf);
594 
595   EXPECT_EQ(
596       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
597                       msg.SerializeAsArray(), kNone),
598       R"({"field_fixed64":[42,3000000000000]})");
599 }
600 
601 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed64Int64) {
602   protozero::HeapBuffered<PackedRepeatedFields> msg;
603   protozero::PackedFixedSizeInt<int64_t> buf;
604   buf.Append(-42);
605   buf.Append(3000000000000);
606   msg->set_field_sfixed64(buf);
607 
608   EXPECT_EQ(
609       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
610                       msg.SerializeAsArray(), kNone),
611       R"({"field_sfixed64":[-42,3000000000000]})");
612 }
613 
614 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixed64Double) {
615   protozero::HeapBuffered<PackedRepeatedFields> msg;
616   protozero::PackedFixedSizeInt<double> buf;
617   buf.Append(-42);
618   buf.Append(42.125);
619   msg->set_field_double(buf);
620 
621   std::string output =
622       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
623                       msg.SerializeAsArray(), kPretty);
624   EXPECT_THAT(base::SplitString(output, "\n"),
625               ElementsAre("{", R"(  "field_double": [)", StartsWith("    -42"),
626                           StartsWith("    42.125"), R"(  ])", R"(})"));
627 }
628 
629 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedSmallEnum) {
630   protozero::HeapBuffered<PackedRepeatedFields> msg;
631   protozero::PackedVarInt buf;
632   buf.Append(1);
633   buf.Append(0);
634   buf.Append(-1);
635   msg->set_small_enum(buf);
636 
637   EXPECT_EQ(
638       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
639                       msg.SerializeAsArray(), kNone),
640       R"({"small_enum":["TO_BE","NOT_TO_BE",-1]})");
641 }
642 
643 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedSignedEnum) {
644   protozero::HeapBuffered<PackedRepeatedFields> msg;
645   protozero::PackedVarInt buf;
646   buf.Append(1);
647   buf.Append(0);
648   buf.Append(-1);
649   buf.Append(-100);
650   msg->set_signed_enum(buf);
651 
652   EXPECT_EQ(
653       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
654                       msg.SerializeAsArray(), kNone),
655       R"({"signed_enum":["POSITIVE","NEUTRAL","NEGATIVE",-100]})");
656 }
657 
658 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedBigEnum) {
659   protozero::HeapBuffered<PackedRepeatedFields> msg;
660   protozero::PackedVarInt buf;
661   buf.Append(10);
662   buf.Append(100500);
663   buf.Append(-1);
664   msg->set_big_enum(buf);
665 
666   EXPECT_EQ(
667       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
668                       msg.SerializeAsArray(), kNone),
669       R"({"big_enum":["BEGIN","END",-1]})");
670 }
671 
672 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixedErrShort) {
673   protozero::HeapBuffered<PackedRepeatedFields> msg;
674   std::string buf;
675   buf = "\x01";
676   // buf does not contain enough data for a fixed 64
677   msg->AppendBytes(PackedRepeatedFields::kFieldFixed64FieldNumber, buf.data(),
678                    buf.size());
679 
680   // "protoc --decode", instead, returns an error on stderr and doesn't output
681   // anything at all.
682   EXPECT_EQ(
683       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
684                       msg.SerializeAsArray(), kPretty | kInlineErrors),
685       R"({
686   "field_fixed64": [],
687   "__error": "Decoding failure for field 'field_fixed64'"
688 })");
689 }
690 
691 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedFixedGarbage) {
692   protozero::HeapBuffered<PackedRepeatedFields> msg;
693   protozero::PackedFixedSizeInt<uint64_t> buf;
694   buf.Append(42);
695   buf.Append(3000000000000);
696   std::string buf_and_garbage(reinterpret_cast<const char*>(buf.data()),
697                               buf.size());
698   buf_and_garbage += "\x01";
699   // buf contains extra garbage
700   msg->AppendBytes(PackedRepeatedFields::kFieldFixed64FieldNumber,
701                    buf_and_garbage.data(), buf_and_garbage.size());
702 
703   // "protoc --decode", instead, returns an error on stderr and doesn't output
704   // anything at all.
705   EXPECT_EQ(
706       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
707                       msg.SerializeAsArray(), kInlineErrors),
708       R"({"field_fixed64":[],"__error":"Decoding failure for field 'field_fixed64'"})");
709 }
710 
711 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntShort) {
712   protozero::HeapBuffered<PackedRepeatedFields> msg;
713   std::string buf;
714   buf = "\xFF";
715   // for the varint to be valid, buf should contain another byte.
716   msg->AppendBytes(PackedRepeatedFields::kFieldInt32FieldNumber, buf.data(),
717                    buf.size());
718 
719   // "protoc --decode", instead, returns an error on stderr and doesn't output
720   // anything at all.
721   EXPECT_EQ(
722       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
723                       msg.SerializeAsArray(), kInlineErrors),
724       R"({"field_int32":[],"__error":"Decoding failure for field 'field_int32'"})");
725 }
726 
727 TEST_F(ProtozeroToJsonTestMessageTest, FieldLengthLimitedPackedVarIntGarbage) {
728   protozero::HeapBuffered<PackedRepeatedFields> msg;
729   protozero::PackedVarInt buf;
730   buf.Append(42);
731   buf.Append(105);
732   std::string buf_and_garbage(reinterpret_cast<const char*>(buf.data()),
733                               buf.size());
734   buf_and_garbage += "\xFF";
735   // buf contains extra garbage
736   msg->AppendBytes(PackedRepeatedFields::kFieldInt32FieldNumber,
737                    buf_and_garbage.data(), buf_and_garbage.size());
738 
739   // "protoc --decode", instead:
740   // * doesn't output anything.
741   // * returns an error on stderr.
742   EXPECT_EQ(
743       ProtozeroToJson(pool_, ".protozero.test.protos.PackedRepeatedFields",
744                       msg.SerializeAsArray(), kInlineErrors),
745       R"({"field_int32":[42,105],"__error":"Decoding failure for field 'field_int32'"})");
746 }
747 
748 TEST_F(ProtozeroToJsonTestMessageTest, NestedBackToBack) {
749   protozero::HeapBuffered<EveryField> msg;
750   EveryField* nestedA = msg->add_field_nested();
751   nestedA->set_field_string("Hello, ");
752   EveryField* nestedB = msg->add_field_nested();
753   nestedB->set_field_string("world!");
754 
755   EXPECT_EQ(
756       ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
757                       msg.SerializeAsArray(), kInlineErrors),
758       R"({"field_nested":[{"field_string":"Hello, "},{"field_string":"world!"}]})");
759 }
760 
761 TEST_F(ProtozeroToJsonTestMessageTest, ExtraBytes) {
762   protozero::HeapBuffered<EveryField> msg;
763   EveryField* nested = msg->add_field_nested();
764   nested->set_field_string("hello");
765   std::string garbage("\377\377");
766   nested->AppendRawProtoBytes(garbage.data(), garbage.size());
767 
768   // "protoc --decode", instead:
769   // * doesn't output anything.
770   // * returns an error on stderr.
771   EXPECT_EQ(
772       ProtozeroToJson(pool_, ".protozero.test.protos.EveryField",
773                       msg.SerializeAsArray(), kInlineErrors),
774       R"({"field_nested":[{"field_string":"hello"}],"__error":"2 extra bytes"})");
775 }
776 
777 TEST_F(ProtozeroToJsonTestMessageTest, NonExistingType) {
778   protozero::HeapBuffered<EveryField> msg;
779   msg->set_field_string("hello");
780   ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
781 
782   // "protoc --decode", instead:
783   // * doesn't output anything.
784   // * returns an error on stderr.
785   EXPECT_EQ(ProtozeroToJson(pool_, ".non.existing.type", msg.SerializeAsArray(),
786                             kNone),
787             R"({"500":"hello"})");
788 }
789 
790 }  // namespace
791 }  // namespace protozero_to_json
792 }  // namespace trace_processor
793 }  // namespace perfetto
794