• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/test_messages.pb.h"
31 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
32 
33 // Generated by the protozero plugin.
34 namespace pbtest = protozero::test::protos::pbzero;
35 
36 // Generated by the official protobuf compiler.
37 namespace pbgold = protozero::test::protos;
38 
39 namespace protozero {
40 namespace {
41 
42 constexpr size_t kChunkSize = 42;
43 
TEST(ProtoZeroConformanceTest,SimpleFieldsNoNesting)44 TEST(ProtoZeroConformanceTest, SimpleFieldsNoNesting) {
45   HeapBuffered<pbtest::EveryField> msg{kChunkSize, kChunkSize};
46 
47   msg->set_field_int32(-1);
48   msg->set_field_int64(-333123456789ll);
49   msg->set_field_uint32(600);
50   msg->set_field_uint64(333123456789ll);
51   msg->set_field_sint32(-5);
52   msg->set_field_sint64(-9000);
53   msg->set_field_fixed32(12345);
54   msg->set_field_fixed64(444123450000ll);
55   msg->set_field_sfixed32(-69999);
56   msg->set_field_sfixed64(-200);
57   msg->set_field_float(3.14f);
58   msg->set_field_double(0.5555);
59   msg->set_field_bool(true);
60   msg->set_small_enum(pbtest::SmallEnum::TO_BE);
61   msg->set_signed_enum(pbtest::SignedEnum::NEGATIVE);
62   msg->set_big_enum(pbtest::BigEnum::BEGIN);
63   msg->set_field_string("FizzBuzz");
64   msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"), 4);
65   msg->add_repeated_int32(1);
66   msg->add_repeated_int32(-1);
67   msg->add_repeated_int32(100);
68   msg->add_repeated_int32(2000000);
69 
70   std::string serialized = msg.SerializeAsString();
71   pbgold::EveryField gold_msg;
72   gold_msg.ParseFromString(serialized);
73 
74   EXPECT_EQ(-1, gold_msg.field_int32());
75   EXPECT_EQ(-333123456789ll, gold_msg.field_int64());
76   EXPECT_EQ(600u, gold_msg.field_uint32());
77   EXPECT_EQ(333123456789ull, gold_msg.field_uint64());
78   EXPECT_EQ(-5, gold_msg.field_sint32());
79   EXPECT_EQ(-9000, gold_msg.field_sint64());
80   EXPECT_EQ(12345u, gold_msg.field_fixed32());
81   EXPECT_EQ(444123450000ull, gold_msg.field_fixed64());
82   EXPECT_EQ(-69999, gold_msg.field_sfixed32());
83   EXPECT_EQ(-200, gold_msg.field_sfixed64());
84   EXPECT_FLOAT_EQ(3.14f, gold_msg.field_float());
85   EXPECT_DOUBLE_EQ(0.5555, gold_msg.field_double());
86   EXPECT_EQ(true, gold_msg.field_bool());
87   EXPECT_EQ(pbgold::SmallEnum::TO_BE, gold_msg.small_enum());
88   EXPECT_EQ(pbgold::SignedEnum::NEGATIVE, gold_msg.signed_enum());
89   EXPECT_EQ(pbgold::BigEnum::BEGIN, gold_msg.big_enum());
90   EXPECT_EQ("FizzBuzz", gold_msg.field_string());
91   EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), gold_msg.field_bytes());
92   EXPECT_EQ(4, gold_msg.repeated_int32_size());
93   EXPECT_EQ(1, gold_msg.repeated_int32(0));
94   EXPECT_EQ(-1, gold_msg.repeated_int32(1));
95   EXPECT_EQ(100, gold_msg.repeated_int32(2));
96   EXPECT_EQ(2000000, gold_msg.repeated_int32(3));
97   EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSizeLong()));
98 }
99 
TEST(ProtoZeroConformanceTest,NestedMessages)100 TEST(ProtoZeroConformanceTest, NestedMessages) {
101   HeapBuffered<pbtest::NestedA> msg_a{kChunkSize, kChunkSize};
102 
103   pbtest::NestedA::NestedB* msg_b = msg_a->add_repeated_a();
104   pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->set_value_b();
105   msg_c->set_value_c(321);
106   msg_b = msg_a->add_repeated_a();
107   msg_c = msg_a->set_super_nested();
108   msg_c->set_value_c(1000);
109 
110   std::string serialized = msg_a.SerializeAsString();
111   EXPECT_EQ(serialized.size(), 26u);
112 
113   pbgold::NestedA gold_msg_a;
114   gold_msg_a.ParseFromString(serialized);
115   EXPECT_EQ(2, gold_msg_a.repeated_a_size());
116   EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
117   EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
118   EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
119 }
120 
TEST(ProtoZeroConformanceTest,Extensions)121 TEST(ProtoZeroConformanceTest, Extensions) {
122   HeapBuffered<pbtest::BrowserExtension> msg_a{kChunkSize, kChunkSize};
123 
124   msg_a->set_base_int(4);
125 
126   pbtest::SystemA* msg_b = msg_a->set_extension_a();
127   msg_b->set_int_a(3);
128   msg_b->set_string_a("string a");
129 
130   pbtest::SystemB* msg_c = msg_a->set_extension_b();
131   msg_c->set_int_b(10);
132   msg_c->set_string_b("string b");
133 
134   msg_a->set_base_string("base string");
135 
136   std::string serialized = msg_a.SerializeAsString();
137   pbgold::RealFakeEvent gold_msg_a;
138   gold_msg_a.ParseFromString(serialized);
139 
140   EXPECT_EQ(gold_msg_a.base_int(), 4u);
141   EXPECT_EQ(gold_msg_a.base_string(), "base string");
142 
143   pbgold::SystemA gold_msg_b =
144       gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_a);
145   EXPECT_EQ(gold_msg_b.int_a(), 3u);
146   EXPECT_EQ(gold_msg_b.string_a(), "string a");
147 
148   pbgold::SystemB gold_msg_c =
149       gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_b);
150   EXPECT_EQ(gold_msg_c.int_b(), 10u);
151   EXPECT_EQ(gold_msg_c.string_b(), "string b");
152 }
153 
TEST(ProtoZeroConformanceTest,Import)154 TEST(ProtoZeroConformanceTest, Import) {
155   // Test the includes for indirect public import: library.pbzero.h ->
156   // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h .
157   EXPECT_LE(0u, sizeof(pbtest::TrickyPublicImport));
158 }
159 
TEST(ProtoZeroConformanceTest,FieldNumbers)160 TEST(ProtoZeroConformanceTest, FieldNumbers) {
161   EXPECT_EQ(1, pbtest::CamelCaseFields::kFooBarBazFieldNumber);
162   EXPECT_EQ(2, pbtest::CamelCaseFields::kBarBazFieldNumber);
163   EXPECT_EQ(3, pbtest::CamelCaseFields::kMooMooFieldNumber);
164   EXPECT_EQ(4, pbtest::CamelCaseFields::kURLEncoderFieldNumber);
165   EXPECT_EQ(5, pbtest::CamelCaseFields::kXMapFieldNumber);
166   EXPECT_EQ(6, pbtest::CamelCaseFields::kUrLENcoDerFieldNumber);
167   EXPECT_EQ(7, pbtest::CamelCaseFields::kBigBangFieldNumber);
168   EXPECT_EQ(8, pbtest::CamelCaseFields::kU2FieldNumber);
169   EXPECT_EQ(9, pbtest::CamelCaseFields::kBangBigFieldNumber);
170 }
171 
TEST(ProtoZeroConformanceTest,PackedRepeatedVarint)172 TEST(ProtoZeroConformanceTest, PackedRepeatedVarint) {
173   int values[] = {42, 255, -1};
174 
175   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
176   PackedVarInt buf;
177   for (auto v : values)
178     buf.Append(v);
179   msg->set_field_int32(buf);
180   std::string serialized = msg.SerializeAsString();
181 
182   // Serialized as a length-delimited field with a payload of
183   // concatenated varints. So the size should be:
184   // varint(42) -> 1 byte
185   // varint(255) -> 2 bytes
186   // varint(-1) -> 10 bytes
187   // varint(payload length) -> 1 byte
188   // field type & id(1) -> 1 byte
189   // total: 6 bytes
190   EXPECT_EQ(15u, serialized.size());
191   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
192                 pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
193             static_cast<uint32_t>(serialized[0]));
194 
195   // Correctly parsed by the protobuf library.
196   pbgold::PackedRepeatedFields parsed_gold_msg;
197   parsed_gold_msg.ParseFromString(serialized);
198   ASSERT_THAT(parsed_gold_msg.field_int32(), testing::ElementsAreArray(values));
199 
200   // Encoded identically by the protobuf library.
201   pbgold::PackedRepeatedFields gold_msg;
202   for (auto v : values)
203     gold_msg.add_field_int32(v);
204   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
205 }
206 
TEST(ProtoZeroConformanceTest,PackedRepeatedFixed32)207 TEST(ProtoZeroConformanceTest, PackedRepeatedFixed32) {
208   uint32_t values[] = {1, 2, 4, 8};
209 
210   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
211   PackedFixedSizeInt<uint32_t> buf;
212   for (auto v : values)
213     buf.Append(v);
214   msg->set_field_fixed32(buf);
215   std::string serialized = msg.SerializeAsString();
216 
217   // 4x4 bytes payload + 1 byte length + 1 byte tag & field
218   EXPECT_EQ(18u, serialized.size());
219   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
220                 pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber),
221             static_cast<uint32_t>(serialized[0]));
222 
223   // Correctly parsed by the protobuf library.
224   pbgold::PackedRepeatedFields parsed_gold_msg;
225   parsed_gold_msg.ParseFromString(serialized);
226   ASSERT_THAT(parsed_gold_msg.field_fixed32(),
227               testing::ElementsAreArray(values));
228 
229   // Encoded identically by the protobuf library.
230   pbgold::PackedRepeatedFields gold_msg;
231   for (auto v : values)
232     gold_msg.add_field_fixed32(v);
233   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
234 }
235 
TEST(ProtoZeroConformanceTest,PackedRepeatedFixed64)236 TEST(ProtoZeroConformanceTest, PackedRepeatedFixed64) {
237   int64_t values[] = {1, -2, 4, -8};
238 
239   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
240   PackedFixedSizeInt<int64_t> buf;
241   for (auto v : values)
242     buf.Append(v);
243   msg->set_field_sfixed64(buf);
244   std::string serialized = msg.SerializeAsString();
245 
246   // 4x8 bytes payload + 1 byte length + 1 byte tag & field
247   EXPECT_EQ(34u, serialized.size());
248   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
249                 pbtest::PackedRepeatedFields::kFieldSfixed64FieldNumber),
250             static_cast<uint32_t>(serialized[0]));
251 
252   // Correctly parsed by the protobuf library.
253   pbgold::PackedRepeatedFields parsed_gold_msg;
254   parsed_gold_msg.ParseFromString(serialized);
255   ASSERT_THAT(parsed_gold_msg.field_sfixed64(),
256               testing::ElementsAreArray(values));
257 
258   // Encoded identically by the protobuf library.
259   pbgold::PackedRepeatedFields gold_msg;
260   for (auto v : values)
261     gold_msg.add_field_sfixed64(v);
262   ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
263 }
264 
TEST(ProtoZeroConformanceTest,EmptyPackedRepeatedField)265 TEST(ProtoZeroConformanceTest, EmptyPackedRepeatedField) {
266   HeapBuffered<pbtest::PackedRepeatedFields> msg;
267   PackedVarInt buf;
268   msg->set_field_int32(buf);
269   std::string serialized = msg.SerializeAsString();
270 
271   // Encoded as 2 bytes: tag/field, and a length of zero.
272   EXPECT_EQ(2u, serialized.size());
273   EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
274                 pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
275             static_cast<uint32_t>(serialized[0]));
276   EXPECT_EQ(0, serialized[1]);
277 
278   // Correctly parsed by the protobuf library.
279   pbgold::PackedRepeatedFields parsed_gold_msg;
280   parsed_gold_msg.ParseFromString(serialized);
281   EXPECT_EQ(0, parsed_gold_msg.field_int32_size());
282 }
283 
284 // Tests that the stack -> heap expansion dosn't lose data.
TEST(ProtoZeroConformanceTest,PackedRepeatedResize)285 TEST(ProtoZeroConformanceTest, PackedRepeatedResize) {
286   const int kNumValues = 32768;
287   const int64_t kMultiplier = 10000000;
288   HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
289   PackedFixedSizeInt<int64_t> buf;
290   for (int i = 0; i < kNumValues; i++)
291     buf.Append(i * kMultiplier);
292   msg->set_field_sfixed64(buf);
293   std::string serialized = msg.SerializeAsString();
294 
295   // Correctly parsed by the protobuf library.
296   pbgold::PackedRepeatedFields parsed_gold_msg;
297   parsed_gold_msg.ParseFromString(serialized);
298   ASSERT_EQ(parsed_gold_msg.field_sfixed64().size(), kNumValues);
299   for (int i = 0; i < kNumValues; i++) {
300     ASSERT_EQ(parsed_gold_msg.field_sfixed64(i), i * kMultiplier);
301   }
302 }
303 
TEST(ProtoZeroConformanceTest,EnumToString)304 TEST(ProtoZeroConformanceTest, EnumToString) {
305   EXPECT_STREQ(protozero::test::protos::pbzero::SmallEnum_Name(
306                    protozero::test::protos::pbzero::SmallEnum::TO_BE),
307                "TO_BE");
308   EXPECT_STREQ(protozero::test::protos::pbzero::EveryField::NestedEnum_Name(
309                    protozero::test::protos::pbzero::EveryField::PING),
310                "PING");
311 }
312 
313 }  // namespace
314 }  // namespace protozero
315