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