xref: /aosp_15_r20/external/perfetto/src/protozero/test/protozero_conformance_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2017 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 <limits>
18 #include <memory>
19 #include <vector>
20 
21 #include "perfetto/protozero/message_handle.h"
22 #include "perfetto/protozero/packed_repeated_fields.h"
23 #include "perfetto/protozero/scattered_heap_buffer.h"
24 #include "test/gtest_and_gmock.h"
25 
26 // Autogenerated headers in out/*/gen/
27 #include "src/protozero/test/example_proto/extensions.pb.h"
28 #include "src/protozero/test/example_proto/extensions.pbzero.h"
29 #include "src/protozero/test/example_proto/library.pbzero.h"
30 #include "src/protozero/test/example_proto/other_package/test_messages.pbzero.h"
31 #include "src/protozero/test/example_proto/subpackage/test_messages.pbzero.h"
32 #include "src/protozero/test/example_proto/test_messages.pb.h"
33 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
34 
35 // Generated by the protozero plugin.
36 namespace pbtest = protozero::test::protos::pbzero;
37 namespace pbtest_subpackage = protozero::test::protos::subpackage::pbzero;
38 namespace pbtest_otherpackage = other_package::pbzero;
39 
40 // Generated by the official protobuf compiler.
41 namespace pbgold = protozero::test::protos;
42 namespace pbgold_subpackage = protozero::test::protos::subpackage;
43 namespace pbgold_other_package = other_package;
44 
45 namespace protozero {
46 namespace {
47 
48 constexpr size_t kChunkSize = 42;
49 
TEST(ProtoZeroConformanceTest,SimpleFieldsNoNesting)50 TEST(ProtoZeroConformanceTest, SimpleFieldsNoNesting) {
51   HeapBuffered<pbtest::EveryField> msg{kChunkSize, kChunkSize};
52 
53   msg->set_field_int32(-1);
54   msg->set_field_int64(-333123456789ll);
55   msg->set_field_uint32(600);
56   msg->set_field_uint64(333123456789ll);
57   msg->set_field_sint32(-5);
58   msg->set_field_sint64(-9000);
59   msg->set_field_fixed32(12345);
60   msg->set_field_fixed64(444123450000ll);
61   msg->set_field_sfixed32(-69999);
62   msg->set_field_sfixed64(-200);
63   msg->set_field_float(3.14f);
64   msg->set_field_double(0.5555);
65   msg->set_field_bool(true);
66   msg->set_small_enum(pbtest::SmallEnum::TO_BE);
67   msg->set_signed_enum(pbtest::SignedEnum::NEGATIVE);
68   msg->set_big_enum(pbtest::BigEnum::BEGIN);
69   msg->set_field_string("FizzBuzz");
70   msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"), 4);
71   msg->add_repeated_int32(1);
72   msg->add_repeated_int32(-1);
73   msg->add_repeated_int32(100);
74   msg->add_repeated_int32(2000000);
75 
76   std::string serialized = msg.SerializeAsString();
77   pbgold::EveryField gold_msg;
78   gold_msg.ParseFromString(serialized);
79 
80   EXPECT_EQ(-1, gold_msg.field_int32());
81   EXPECT_EQ(-333123456789ll, gold_msg.field_int64());
82   EXPECT_EQ(600u, gold_msg.field_uint32());
83   EXPECT_EQ(333123456789ull, gold_msg.field_uint64());
84   EXPECT_EQ(-5, gold_msg.field_sint32());
85   EXPECT_EQ(-9000, gold_msg.field_sint64());
86   EXPECT_EQ(12345u, gold_msg.field_fixed32());
87   EXPECT_EQ(444123450000ull, gold_msg.field_fixed64());
88   EXPECT_EQ(-69999, gold_msg.field_sfixed32());
89   EXPECT_EQ(-200, gold_msg.field_sfixed64());
90   EXPECT_FLOAT_EQ(3.14f, gold_msg.field_float());
91   EXPECT_DOUBLE_EQ(0.5555, gold_msg.field_double());
92   EXPECT_EQ(true, gold_msg.field_bool());
93   EXPECT_EQ(pbgold::SmallEnum::TO_BE, gold_msg.small_enum());
94   EXPECT_EQ(pbgold::SignedEnum::NEGATIVE, gold_msg.signed_enum());
95   EXPECT_EQ(pbgold::BigEnum::BEGIN, gold_msg.big_enum());
96   EXPECT_EQ("FizzBuzz", gold_msg.field_string());
97   EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), gold_msg.field_bytes());
98   EXPECT_EQ(4, gold_msg.repeated_int32_size());
99   EXPECT_EQ(1, gold_msg.repeated_int32(0));
100   EXPECT_EQ(-1, gold_msg.repeated_int32(1));
101   EXPECT_EQ(100, gold_msg.repeated_int32(2));
102   EXPECT_EQ(2000000, gold_msg.repeated_int32(3));
103   EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSizeLong()));
104 }
105 
TEST(ProtoZeroConformanceTest,NestedMessages)106 TEST(ProtoZeroConformanceTest, NestedMessages) {
107   HeapBuffered<pbtest::NestedA> msg_a{kChunkSize, kChunkSize};
108 
109   pbtest::NestedA::NestedB* msg_b = msg_a->add_repeated_a();
110   pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->set_value_b();
111   msg_c->set_value_c(321);
112   msg_b = msg_a->add_repeated_a();
113   msg_c = msg_a->set_super_nested();
114   msg_c->set_value_c(1000);
115 
116   std::string serialized = msg_a.SerializeAsString();
117   EXPECT_EQ(serialized.size(), 14u);
118 
119   pbgold::NestedA gold_msg_a;
120   gold_msg_a.ParseFromString(serialized);
121   EXPECT_EQ(2, gold_msg_a.repeated_a_size());
122   EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
123   EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
124   EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
125 }
126 
TEST(ProtoZeroConformanceTest,Extensions)127 TEST(ProtoZeroConformanceTest, Extensions) {
128   HeapBuffered<pbtest::BrowserExtension> msg_a{kChunkSize, kChunkSize};
129 
130   msg_a->set_base_int(4);
131 
132   pbtest::SystemA* msg_b = msg_a->set_extension_a();
133   msg_b->set_int_a(3);
134   msg_b->set_string_a("string a");
135 
136   pbtest::SystemB* msg_c = msg_a->set_extension_b();
137   msg_c->set_int_b(10);
138   msg_c->set_string_b("string b");
139 
140   msg_a->set_base_string("base string");
141 
142   std::string serialized = msg_a.SerializeAsString();
143   pbgold::RealFakeEvent gold_msg_a;
144   gold_msg_a.ParseFromString(serialized);
145 
146   EXPECT_EQ(gold_msg_a.base_int(), 4u);
147   EXPECT_EQ(gold_msg_a.base_string(), "base string");
148 
149   pbgold::SystemA gold_msg_b =
150       gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_a);
151   EXPECT_EQ(gold_msg_b.int_a(), 3u);
152   EXPECT_EQ(gold_msg_b.string_a(), "string a");
153 
154   pbgold::SystemB gold_msg_c =
155       gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_b);
156   EXPECT_EQ(gold_msg_c.int_b(), 10u);
157   EXPECT_EQ(gold_msg_c.string_b(), "string b");
158 }
159 
TEST(ProtoZeroConformanceTest,Import)160 TEST(ProtoZeroConformanceTest, Import) {
161   // Test the includes for indirect public import: library.pbzero.h ->
162   // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h .
163   EXPECT_LE(0u, sizeof(pbtest::TrickyPublicImport));
164 }
165 
TEST(ProtoZeroConformanceTest,FieldNumbers)166 TEST(ProtoZeroConformanceTest, FieldNumbers) {
167   EXPECT_EQ(1, pbtest::CamelCaseFields::kFooBarBazFieldNumber);
168   EXPECT_EQ(2, pbtest::CamelCaseFields::kBarBazFieldNumber);
169   EXPECT_EQ(3, pbtest::CamelCaseFields::kMooMooFieldNumber);
170   EXPECT_EQ(4, pbtest::CamelCaseFields::kURLEncoderFieldNumber);
171   EXPECT_EQ(5, pbtest::CamelCaseFields::kXMapFieldNumber);
172   EXPECT_EQ(6, pbtest::CamelCaseFields::kUrLENcoDerFieldNumber);
173   EXPECT_EQ(7, pbtest::CamelCaseFields::kBigBangFieldNumber);
174   EXPECT_EQ(8, pbtest::CamelCaseFields::kU2FieldNumber);
175   EXPECT_EQ(9, pbtest::CamelCaseFields::kBangBigFieldNumber);
176 }
177 
TEST(ProtoZeroConformanceTest,PackedRepeatedVarint)178 TEST(ProtoZeroConformanceTest, PackedRepeatedVarint) {
179   int values[] = {42, 255, -1};
180 
181   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
182   PackedVarInt buf;
183   for (auto v : values)
184     buf.Append(v);
185   msg->set_field_int32(buf);
186   std::string serialized = msg.SerializeAsString();
187 
188   // Serialized as a length-delimited field with a payload of
189   // concatenated varints. So the size should be:
190   // varint(42) -> 1 byte
191   // varint(255) -> 2 bytes
192   // varint(-1) -> 10 bytes
193   // varint(payload length) -> 1 byte
194   // field type & id(1) -> 1 byte
195   // total: 6 bytes
196   EXPECT_EQ(15u, serialized.size());
197   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
198                 pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
199             static_cast<uint32_t>(serialized[0]));
200 
201   // Correctly parsed by the protobuf library.
202   pbgold::PackedRepeatedFields parsed_gold_msg;
203   parsed_gold_msg.ParseFromString(serialized);
204   ASSERT_THAT(parsed_gold_msg.field_int32(), testing::ElementsAreArray(values));
205 
206   // Encoded identically by the protobuf library.
207   pbgold::PackedRepeatedFields gold_msg;
208   for (auto v : values)
209     gold_msg.add_field_int32(v);
210   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
211 }
212 
TEST(ProtoZeroConformanceTest,PackedRepeatedFixed32)213 TEST(ProtoZeroConformanceTest, PackedRepeatedFixed32) {
214   uint32_t values[] = {1, 2, 4, 8};
215 
216   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
217   PackedFixedSizeInt<uint32_t> buf;
218   for (auto v : values)
219     buf.Append(v);
220   msg->set_field_fixed32(buf);
221   std::string serialized = msg.SerializeAsString();
222 
223   // 4x4 bytes payload + 1 byte length + 1 byte tag & field
224   EXPECT_EQ(18u, serialized.size());
225   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
226                 pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber),
227             static_cast<uint32_t>(serialized[0]));
228 
229   // Correctly parsed by the protobuf library.
230   pbgold::PackedRepeatedFields parsed_gold_msg;
231   parsed_gold_msg.ParseFromString(serialized);
232   ASSERT_THAT(parsed_gold_msg.field_fixed32(),
233               testing::ElementsAreArray(values));
234 
235   // Encoded identically by the protobuf library.
236   pbgold::PackedRepeatedFields gold_msg;
237   for (auto v : values)
238     gold_msg.add_field_fixed32(v);
239   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
240 }
241 
TEST(ProtoZeroConformanceTest,PackedRepeatedFixed64)242 TEST(ProtoZeroConformanceTest, PackedRepeatedFixed64) {
243   int64_t values[] = {1, -2, 4, -8};
244 
245   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
246   PackedFixedSizeInt<int64_t> buf;
247   for (auto v : values)
248     buf.Append(v);
249   msg->set_field_sfixed64(buf);
250   std::string serialized = msg.SerializeAsString();
251 
252   // 4x8 bytes payload + 1 byte length + 1 byte tag & field
253   EXPECT_EQ(34u, serialized.size());
254   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
255                 pbtest::PackedRepeatedFields::kFieldSfixed64FieldNumber),
256             static_cast<uint32_t>(serialized[0]));
257 
258   // Correctly parsed by the protobuf library.
259   pbgold::PackedRepeatedFields parsed_gold_msg;
260   parsed_gold_msg.ParseFromString(serialized);
261   ASSERT_THAT(parsed_gold_msg.field_sfixed64(),
262               testing::ElementsAreArray(values));
263 
264   // Encoded identically by the protobuf library.
265   pbgold::PackedRepeatedFields gold_msg;
266   for (auto v : values)
267     gold_msg.add_field_sfixed64(v);
268   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
269 }
270 
TEST(ProtoZeroConformanceTest,EmptyPackedRepeatedField)271 TEST(ProtoZeroConformanceTest, EmptyPackedRepeatedField) {
272   HeapBuffered<pbtest::PackedRepeatedFields> msg;
273   PackedVarInt buf;
274   msg->set_field_int32(buf);
275   std::string serialized = msg.SerializeAsString();
276 
277   // Encoded as 2 bytes: tag/field, and a length of zero.
278   EXPECT_EQ(2u, serialized.size());
279   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
280                 pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
281             static_cast<uint32_t>(serialized[0]));
282   EXPECT_EQ(0, serialized[1]);
283 
284   // Correctly parsed by the protobuf library.
285   pbgold::PackedRepeatedFields parsed_gold_msg;
286   parsed_gold_msg.ParseFromString(serialized);
287   EXPECT_EQ(0, parsed_gold_msg.field_int32_size());
288 }
289 
290 // Tests that the stack -> heap expansion dosn't lose data.
TEST(ProtoZeroConformanceTest,PackedRepeatedResize)291 TEST(ProtoZeroConformanceTest, PackedRepeatedResize) {
292   const int kNumValues = 32768;
293   const int64_t kMultiplier = 10000000;
294   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
295   PackedFixedSizeInt<int64_t> buf;
296   for (int i = 0; i < kNumValues; i++)
297     buf.Append(i * kMultiplier);
298   msg->set_field_sfixed64(buf);
299   std::string serialized = msg.SerializeAsString();
300 
301   // Correctly parsed by the protobuf library.
302   pbgold::PackedRepeatedFields parsed_gold_msg;
303   parsed_gold_msg.ParseFromString(serialized);
304   ASSERT_EQ(parsed_gold_msg.field_sfixed64().size(), kNumValues);
305   for (int i = 0; i < kNumValues; i++) {
306     ASSERT_EQ(parsed_gold_msg.field_sfixed64(i), i * kMultiplier);
307   }
308 }
309 
TEST(ProtoZeroConformanceTest,EnumToString)310 TEST(ProtoZeroConformanceTest, EnumToString) {
311   EXPECT_STREQ(protozero::test::protos::pbzero::SmallEnum_Name(
312                    protozero::test::protos::pbzero::SmallEnum::TO_BE),
313                "TO_BE");
314   EXPECT_STREQ(protozero::test::protos::pbzero::EveryField::NestedEnum_Name(
315                    protozero::test::protos::pbzero::EveryField::PING),
316                "PING");
317 }
318 
TEST(ProtoZeroConformanceTest,DifferentPackages)319 TEST(ProtoZeroConformanceTest, DifferentPackages) {
320   HeapBuffered<pbtest::DifferentPackages> msg{kChunkSize, kChunkSize};
321 
322   // Pupulate fields defined in "protozero.test.protos.subpackage"
323   pbtest_subpackage::Message* msgSubpackage = msg->set_subpackage_message();
324   msgSubpackage->set_field_int32(1);
325   msgSubpackage->set_field_enum(pbtest_subpackage::Enum::A);
326   msgSubpackage->set_field_nested_enum(
327       pbtest_subpackage::Message::NestedEnum::C);
328   msg->set_subpackage_nested_message()->set_field_int32(2);
329   msg->set_subpackage_enum(pbtest_subpackage::Enum::B);
330   msg->set_subpackage_nested_enum(pbtest_subpackage::Message_NestedEnum::D);
331 
332   // Pupulate fields defined in "other_package"
333   pbtest_otherpackage::Message* msgOtherPackage =
334       msg->set_otherpackage_message();
335   msgOtherPackage->set_field_int32(11);
336   msgOtherPackage->set_field_enum(pbtest_otherpackage::Enum::A);
337   msgOtherPackage->set_field_nested_enum(
338       pbtest_otherpackage::Message::NestedEnum::C);
339   msg->set_otherpackage_nested_message()->set_field_int32(12);
340   msg->set_otherpackage_enum(pbtest_otherpackage::Enum::B);
341   msg->set_otherpackage_nested_enum(pbtest_otherpackage::Message_NestedEnum::D);
342 
343   // Deserialize into golden proto
344   std::string serialized = msg.SerializeAsString();
345   pbgold::DifferentPackages gold_msg;
346   gold_msg.ParseFromString(serialized);
347   EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSizeLong()));
348 
349   // Check fields defined in "protozero.test.protos.subpackage"
350   EXPECT_EQ(1, gold_msg.subpackage_message().field_int32());
351   EXPECT_EQ(pbgold_subpackage::Enum::A,
352             gold_msg.subpackage_message().field_enum());
353   EXPECT_EQ(pbgold_subpackage::Message_NestedEnum_C,
354             gold_msg.subpackage_message().field_nested_enum());
355   EXPECT_EQ(2, gold_msg.subpackage_nested_message().field_int32());
356   EXPECT_EQ(pbgold_subpackage::Enum::B, gold_msg.subpackage_enum());
357   EXPECT_EQ(pbgold_subpackage::Message_NestedEnum_D,
358             gold_msg.subpackage_nested_enum());
359 
360   // Check fields defined in "other_package"
361   EXPECT_EQ(11, gold_msg.otherpackage_message().field_int32());
362   EXPECT_EQ(pbgold_other_package::Enum::A,
363             gold_msg.otherpackage_message().field_enum());
364   EXPECT_EQ(pbgold_other_package::Message_NestedEnum_C,
365             gold_msg.otherpackage_message().field_nested_enum());
366   EXPECT_EQ(12, gold_msg.otherpackage_nested_message().field_int32());
367   EXPECT_EQ(pbgold_other_package::Enum::B, gold_msg.otherpackage_enum());
368   EXPECT_EQ(pbgold_other_package::Message_NestedEnum_D,
369             gold_msg.otherpackage_nested_enum());
370 }
371 
372 }  // namespace
373 }  // namespace protozero
374