xref: /aosp_15_r20/external/perfetto/src/protozero/test/cppgen_conformance_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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 "test/gtest_and_gmock.h"
24 
25 // Autogenerated headers in out/*/gen/
26 #include "src/protozero/test/example_proto/library.gen.h"
27 #include "src/protozero/test/example_proto/other_package/test_messages.gen.h"
28 #include "src/protozero/test/example_proto/subpackage/test_messages.gen.h"
29 #include "src/protozero/test/example_proto/test_messages.gen.h"
30 #include "src/protozero/test/example_proto/test_messages.pb.h"
31 
32 // Generated by the cppgen compiler.
33 namespace pbtest = protozero::test::protos::gen;
34 namespace pbtest_subpackage = protozero::test::protos::subpackage::gen;
35 namespace pbtest_otherpackage = other_package::gen;
36 
37 // Generated by the official protobuf compiler.
38 namespace pbgold = protozero::test::protos;
39 namespace pbgold_subpackage = protozero::test::protos::subpackage;
40 namespace pbgold_other_package = other_package;
41 
42 namespace protozero {
43 namespace {
44 
45 using testing::ElementsAreArray;
46 
47 // The two functions below are templated because they are re-used both on the
48 // libprotobuf and protozero versions to check both libproto -> zero and
49 // zero -> libproto compatibility.
50 template <typename T>
SetTestingFields(T * msg)51 void SetTestingFields(T* msg) {
52   msg->set_field_int32(-1);
53   msg->set_field_int64(-333123456789ll);
54   msg->set_field_uint32(600);
55   msg->set_field_uint64(333123456789ll);
56   msg->set_field_sint32(-5);
57   msg->set_field_sint64(-9000);
58   msg->set_field_fixed32(12345);
59   msg->set_field_fixed64(444123450000ll);
60   msg->set_field_sfixed32(-69999);
61   msg->set_field_sfixed64(-200);
62   msg->set_field_float(3.14f);
63   msg->set_field_double(0.5555);
64   msg->set_field_bool(true);
65 
66   msg->set_small_enum(decltype(msg->small_enum())::TO_BE);
67   msg->set_signed_enum(decltype(msg->signed_enum())::NEGATIVE);
68   msg->set_big_enum(decltype(msg->big_enum())::BEGIN);
69 
70   msg->set_field_string("FizzBuzz");
71   msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"),
72                        4u);
73   msg->add_repeated_int32(1);
74   msg->add_repeated_int32(-1);
75   msg->add_repeated_int32(100);
76   msg->add_repeated_int32(2000000);
77 }
78 
79 template <typename T>
CheckTestingFields(const T & msg)80 void CheckTestingFields(const T& msg) {
81   EXPECT_EQ(-1, msg.field_int32());
82   EXPECT_EQ(-333123456789ll, msg.field_int64());
83   EXPECT_EQ(600u, msg.field_uint32());
84   EXPECT_EQ(333123456789ull, msg.field_uint64());
85   EXPECT_EQ(-5, msg.field_sint32());
86   EXPECT_EQ(-9000, msg.field_sint64());
87   EXPECT_EQ(12345u, msg.field_fixed32());
88   EXPECT_EQ(444123450000ull, msg.field_fixed64());
89   EXPECT_EQ(-69999, msg.field_sfixed32());
90   EXPECT_EQ(-200, msg.field_sfixed64());
91   EXPECT_FLOAT_EQ(3.14f, msg.field_float());
92   EXPECT_DOUBLE_EQ(0.5555, msg.field_double());
93   EXPECT_EQ(true, msg.field_bool());
94   EXPECT_EQ(decltype(msg.small_enum())::TO_BE, msg.small_enum());
95   EXPECT_EQ(decltype(msg.signed_enum())::NEGATIVE, msg.signed_enum());
96   EXPECT_EQ(decltype(msg.big_enum())::BEGIN, msg.big_enum());
97   EXPECT_EQ("FizzBuzz", msg.field_string());
98   EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), msg.field_bytes());
99   ASSERT_THAT(msg.repeated_int32(), ElementsAreArray({1, -1, 100, 2000000}));
100 }
101 
TEST(ProtoCppConformanceTest,GenEncode_GoldDecode)102 TEST(ProtoCppConformanceTest, GenEncode_GoldDecode) {
103   pbtest::EveryField msg;
104   SetTestingFields(&msg);
105   std::string serialized = msg.SerializeAsString();
106 
107   pbgold::EveryField gold_msg;
108   gold_msg.ParseFromString(serialized);
109   CheckTestingFields(gold_msg);
110   EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSizeLong()));
111 }
112 
TEST(ProtoCppConformanceTest,GoldEncode_GenDecode)113 TEST(ProtoCppConformanceTest, GoldEncode_GenDecode) {
114   pbgold::EveryField gold_msg;
115   SetTestingFields(&gold_msg);
116   std::string serialized = gold_msg.SerializeAsString();
117 
118   pbtest::EveryField msg;
119   EXPECT_TRUE(msg.ParseFromString(serialized));
120   CheckTestingFields(msg);
121 }
122 
TEST(ProtoCppConformanceTest,GenEncode_GenDecode)123 TEST(ProtoCppConformanceTest, GenEncode_GenDecode) {
124   pbtest::EveryField msg;
125   SetTestingFields(&msg);
126   std::string serialized = msg.SerializeAsString();
127 
128   pbtest::EveryField dec_msg;
129   dec_msg.ParseFromString(serialized);
130   CheckTestingFields(dec_msg);
131   EXPECT_EQ(serialized.size(), dec_msg.SerializeAsString().size());
132 }
133 
TEST(ProtoCppConformanceTest,NestedMessages)134 TEST(ProtoCppConformanceTest, NestedMessages) {
135   pbtest::NestedA msg_a;
136   pbtest::NestedA::NestedB* msg_b = msg_a.add_repeated_a();
137   pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->mutable_value_b();
138   msg_c->set_value_c(321);
139   msg_b = msg_a.add_repeated_a();
140   msg_a.mutable_super_nested()->set_value_c(1000);
141   std::string serialized = msg_a.SerializeAsString();
142 
143   pbgold::NestedA gold_msg_a;
144   gold_msg_a.ParseFromString(serialized);
145   EXPECT_EQ(2, gold_msg_a.repeated_a_size());
146   EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
147   EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
148   EXPECT_EQ(gold_msg_a.repeated_a(1).value_b().value_c(), 0);
149   EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
150 }
151 
152 // Tests that unknown fields are preserved when re-serializing. This test uses
153 // the messages NestedA and NestedA_V2, where NestedA_V2 mimics a future
154 // extension of NestedA. It starts filling the V2 version, than decodes it with
155 // V1, then re-encodes V1 and decodes with V2 and finally check that all the V2
156 // original fields have been preserved.
TEST(ProtoCppConformanceTest,PreserveUnknownFields)157 TEST(ProtoCppConformanceTest, PreserveUnknownFields) {
158   std::string serialized;
159   {
160     pbtest::TestVersioning_V2 msg_v2;
161     msg_v2.set_root_int(10);
162     msg_v2.set_root_int_v2(11);
163     msg_v2.add_enumz(pbtest::TestVersioning_V2::ONE);
164     msg_v2.add_enumz(pbtest::TestVersioning_V2::TWO);
165     msg_v2.add_enumz(pbtest::TestVersioning_V2::THREE_V2);
166     msg_v2.set_root_string("root-string");
167     msg_v2.add_rep_string("root-rep-string-1");
168     msg_v2.add_rep_string("root-rep-string-2");
169     for (int i = 0; i < 3; i++) {
170       auto* sub1 = i == 0 ? msg_v2.mutable_sub1() : msg_v2.add_sub1_rep();
171       sub1->set_sub1_int(12);
172       sub1->set_sub1_string("sub1-string");
173       sub1->set_sub1_int_v2(13);
174       sub1->set_sub1_string_v2("sub1-string-v2");
175 
176       auto* sub2 = i == 0 ? msg_v2.mutable_sub2() : msg_v2.add_sub2_rep();
177       sub2->set_sub2_int(14);
178       sub2->set_sub2_string("sub2-string");
179     }
180     {
181       pbtest::TestVersioning_V2::Sub1_V2 lazy;
182       lazy.set_sub1_int(15);
183       lazy.set_sub1_string("sub1-lazy-string");
184       lazy.set_sub1_int_v2(16);
185       lazy.set_sub1_string_v2("sub1-lazy-string-v2");
186       msg_v2.set_sub1_lazy_raw(lazy.SerializeAsString());
187     }
188     {
189       pbtest::TestVersioning_V2::Sub2_V2 lazy;
190       lazy.set_sub2_int(17);
191       lazy.set_sub2_string("sub2-v2-lazy-string");
192       msg_v2.set_sub2_lazy_raw(lazy.SerializeAsString());
193     }
194 
195     serialized = msg_v2.SerializeAsString();
196   }
197 
198   // Now decode with an earlier version that has less fields. Then re-serialize
199   // the v1 message.
200   {
201     pbtest::TestVersioning_V1 msg_v1;
202     EXPECT_TRUE(msg_v1.ParseFromString(serialized));
203     EXPECT_EQ(msg_v1.root_int(), 10);
204     EXPECT_EQ(msg_v1.enumz_size(), 3);
205     // These are to workaround "ODR-usage" rules that would require that the
206     // constexpr in the .gen.h file have a matching symbol definition in the .cc
207     // file.
208     const auto ONE = pbtest::TestVersioning_V1::ONE;
209     const auto TWO = pbtest::TestVersioning_V1::TWO;
210     EXPECT_EQ(msg_v1.enumz()[0], ONE);
211     EXPECT_EQ(msg_v1.enumz()[1], TWO);
212     EXPECT_EQ(static_cast<int>(msg_v1.enumz()[2]), 3);
213     EXPECT_EQ(msg_v1.root_string(), "root-string");
214     EXPECT_EQ(msg_v1.rep_string_size(), 2);
215     EXPECT_EQ(msg_v1.rep_string()[0], "root-rep-string-1");
216     EXPECT_EQ(msg_v1.rep_string()[1], "root-rep-string-2");
217     EXPECT_EQ(msg_v1.sub1_rep_size(), 2);
218     for (size_t i = 0; i < 3; i++) {
219       auto* sub1 = i == 0 ? &msg_v1.sub1() : &msg_v1.sub1_rep()[i - 1];
220       EXPECT_EQ(sub1->sub1_int(), 12);
221       EXPECT_EQ(sub1->sub1_string(), "sub1-string");
222     }
223 
224     // Append an extra field and change the valaue of an existing one before
225     // re-serializing.
226     msg_v1.set_root_int(101);
227     msg_v1.add_rep_string("extra-string");
228     serialized = msg_v1.SerializeAsString();
229   }
230 
231   // Decode the re-serialized v1 message with with v2. Check that the _v2
232   // fields have been preserved in the double de/serializataion across versions.
233   {
234     pbtest::TestVersioning_V2 msg_v2;
235     EXPECT_TRUE(msg_v2.ParseFromString(serialized));
236     EXPECT_EQ(msg_v2.root_int(), 101);
237     EXPECT_EQ(msg_v2.root_int_v2(), 11);
238     EXPECT_EQ(msg_v2.enumz_size(), 3);
239     const auto ONE = pbtest::TestVersioning_V2::ONE;
240     const auto TWO = pbtest::TestVersioning_V2::TWO;
241     const auto THREE_V2 = pbtest::TestVersioning_V2::THREE_V2;
242     EXPECT_EQ(msg_v2.enumz()[0], ONE);
243     EXPECT_EQ(msg_v2.enumz()[1], TWO);
244     EXPECT_EQ(msg_v2.enumz()[2], THREE_V2);
245     EXPECT_EQ(msg_v2.root_string(), "root-string");
246     EXPECT_EQ(msg_v2.rep_string_size(), 3);
247     EXPECT_EQ(msg_v2.rep_string()[0], "root-rep-string-1");
248     EXPECT_EQ(msg_v2.rep_string()[1], "root-rep-string-2");
249     EXPECT_EQ(msg_v2.rep_string()[2], "extra-string");
250     EXPECT_EQ(msg_v2.sub1_rep_size(), 2);
251     for (size_t i = 0; i < 3; i++) {
252       auto* sub1 = i == 0 ? &msg_v2.sub1() : &msg_v2.sub1_rep()[i - 1];
253       EXPECT_EQ(sub1->sub1_int(), 12);
254       EXPECT_EQ(sub1->sub1_string(), "sub1-string");
255       EXPECT_EQ(sub1->sub1_int_v2(), 13);
256       EXPECT_EQ(sub1->sub1_string_v2(), "sub1-string-v2");
257       auto* sub2 = i == 0 ? &msg_v2.sub2() : &msg_v2.sub2_rep()[i - 1];
258       EXPECT_EQ(sub2->sub2_int(), 14);
259       EXPECT_EQ(sub2->sub2_string(), "sub2-string");
260     }
261     {
262       pbtest::TestVersioning_V2::Sub1_V2 lazy;
263       EXPECT_TRUE(lazy.ParseFromString(msg_v2.sub1_lazy_raw()));
264       EXPECT_EQ(lazy.sub1_int(), 15);
265       EXPECT_EQ(lazy.sub1_string(), "sub1-lazy-string");
266       EXPECT_EQ(lazy.sub1_int_v2(), 16);
267       EXPECT_EQ(lazy.sub1_string_v2(), "sub1-lazy-string-v2");
268     }
269     {
270       pbtest::TestVersioning_V2::Sub2_V2 lazy;
271       EXPECT_TRUE(lazy.ParseFromString(msg_v2.sub2_lazy_raw()));
272       EXPECT_EQ(lazy.sub2_int(), 17);
273       EXPECT_EQ(lazy.sub2_string(), "sub2-v2-lazy-string");
274     }
275   }
276 }
277 
278 // Checks that unset fields aren't zero-initialized in the decode -> re-encode
279 // process.
TEST(ProtoCppConformanceTest,DontDefaultInitialize)280 TEST(ProtoCppConformanceTest, DontDefaultInitialize) {
281   pbtest::EveryField msg;
282   EXPECT_FALSE(msg.has_field_int32());
283   msg.set_field_int32(0);
284   EXPECT_TRUE(msg.has_field_int32());
285 
286   EXPECT_FALSE(msg.has_field_float());
287   msg.set_field_float(.0f);
288   EXPECT_TRUE(msg.has_field_float());
289 
290   EXPECT_FALSE(msg.has_field_string());
291   msg.set_field_string("");
292   EXPECT_TRUE(msg.has_field_string());
293 
294   pbtest::EveryField dec;
295   dec.ParseFromString(msg.SerializeAsString());
296   std::string reserialized = dec.SerializeAsString();
297 
298   pbgold::EveryField gold_msg;
299   gold_msg.ParseFromString(reserialized);
300   EXPECT_TRUE(gold_msg.has_field_int32());
301   EXPECT_EQ(gold_msg.field_int32(), 0);
302   EXPECT_TRUE(gold_msg.has_field_float());
303   EXPECT_FLOAT_EQ(gold_msg.field_float(), .0f);
304   EXPECT_TRUE(gold_msg.has_field_string());
305   EXPECT_EQ(gold_msg.field_string(), "");
306   EXPECT_FALSE(gold_msg.has_field_int64());
307   EXPECT_FALSE(gold_msg.has_field_uint64());
308   EXPECT_FALSE(gold_msg.has_field_bytes());
309 }
310 
311 // Tests serialization and deserialization of packed encoding fields.
TEST(ProtoCppConformanceTest,PackedRepeatedFields)312 TEST(ProtoCppConformanceTest, PackedRepeatedFields) {
313   std::string serialized;
314   {
315     pbtest::PackedRepeatedFields msg;
316 
317     for (int i = -100; i < 100; i++)
318       msg.add_field_int32(i);
319 
320     for (uint32_t i = 100; i < 200; i++)
321       msg.add_field_fixed32(i);
322 
323     for (int64_t i = 5000000000; i < 5000001000; i++)
324       msg.add_field_sfixed64(i);
325 
326     serialized = msg.SerializeAsString();
327   }
328   {
329     pbtest::PackedRepeatedFields msg;
330     EXPECT_TRUE(msg.ParseFromString(serialized));
331 
332     std::vector<int> exp_int32;
333     for (int i = -100; i < 100; i++)
334       exp_int32.emplace_back(i);
335     ASSERT_THAT(msg.field_int32(), ElementsAreArray(exp_int32));
336 
337     std::vector<uint32_t> exp_fixed32;
338     for (uint32_t i = 100; i < 200; i++)
339       exp_fixed32.emplace_back(i);
340     ASSERT_THAT(msg.field_fixed32(), ElementsAreArray(exp_fixed32));
341 
342     std::vector<int64_t> exp_sfixed64;
343     for (int64_t i = 5000000000; i < 5000001000; i++)
344       exp_sfixed64.emplace_back(i);
345     ASSERT_THAT(msg.field_sfixed64(), ElementsAreArray(exp_sfixed64));
346   }
347 }
348 
TEST(ProtoCppConformanceTest,DifferentPackages)349 TEST(ProtoCppConformanceTest, DifferentPackages) {
350   pbtest::DifferentPackages msg;
351 
352   // Pupulate fields defined in "protozero.test.protos.subpackage"
353   pbtest_subpackage::Message* msgSubpackage = msg.mutable_subpackage_message();
354   msgSubpackage->set_field_int32(1);
355   msgSubpackage->set_field_enum(pbtest_subpackage::Enum::A);
356   msgSubpackage->set_field_nested_enum(pbtest_subpackage::Message_NestedEnum_C);
357   msg.mutable_subpackage_nested_message()->set_field_int32(2);
358   msg.set_subpackage_enum(pbtest_subpackage::Enum::B);
359   msg.set_subpackage_nested_enum(pbtest_subpackage::Message_NestedEnum_D);
360 
361   // Pupulate fields defined in "other_package"
362   pbtest_otherpackage::Message* msgOtherPackage =
363       msg.mutable_otherpackage_message();
364   msgOtherPackage->set_field_int32(11);
365   msgOtherPackage->set_field_enum(pbtest_otherpackage::Enum::A);
366   msgOtherPackage->set_field_nested_enum(
367       pbtest_otherpackage::Message_NestedEnum_C);
368   msg.mutable_otherpackage_nested_message()->set_field_int32(12);
369   msg.set_otherpackage_enum(pbtest_otherpackage::Enum::B);
370   msg.set_otherpackage_nested_enum(pbtest_otherpackage::Message_NestedEnum_D);
371 
372   // Deserialize into golden proto
373   std::string serialized = msg.SerializeAsString();
374   pbgold::DifferentPackages gold_msg;
375   gold_msg.ParseFromString(serialized);
376   EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSizeLong()));
377 
378   // Check fields defined in "protozero.test.protos.subpackage"
379   EXPECT_EQ(1, gold_msg.subpackage_message().field_int32());
380   EXPECT_EQ(pbgold_subpackage::Enum::A,
381             gold_msg.subpackage_message().field_enum());
382   EXPECT_EQ(pbgold_subpackage::Message_NestedEnum_C,
383             gold_msg.subpackage_message().field_nested_enum());
384   EXPECT_EQ(2, gold_msg.subpackage_nested_message().field_int32());
385   EXPECT_EQ(pbgold_subpackage::Enum::B, gold_msg.subpackage_enum());
386   EXPECT_EQ(pbgold_subpackage::Message_NestedEnum_D,
387             gold_msg.subpackage_nested_enum());
388 
389   // Check fields defined in "other_package"
390   EXPECT_EQ(11, gold_msg.otherpackage_message().field_int32());
391   EXPECT_EQ(pbgold_other_package::Enum::A,
392             gold_msg.otherpackage_message().field_enum());
393   EXPECT_EQ(pbgold_other_package::Message_NestedEnum_C,
394             gold_msg.otherpackage_message().field_nested_enum());
395   EXPECT_EQ(12, gold_msg.otherpackage_nested_message().field_int32());
396   EXPECT_EQ(pbgold_other_package::Enum::B, gold_msg.otherpackage_enum());
397   EXPECT_EQ(pbgold_other_package::Message_NestedEnum_D,
398             gold_msg.otherpackage_nested_enum());
399 }
400 }  // namespace
401 }  // namespace protozero
402