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 "gtest/gtest.h"
22 #include "perfetto/protozero/message_handle.h"
23 #include "src/protozero/test/fake_scattered_buffer.h"
24
25 // Autogenerated headers in out/*/gen/
26 #include "src/protozero/test/example_proto/library.pbzero.h"
27 #include "src/protozero/test/example_proto/test_messages.pb.h"
28 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
29
30 namespace pbtest = foo::bar::pbzero; // Generated by the protozero plugin.
31 namespace pbgold = foo::bar; // Generated by the official protobuf compiler.
32
33 namespace protozero {
34 namespace {
35
36 constexpr size_t kChunkSize = 42;
37
38 class ProtoZeroConformanceTest : public ::testing::Test {
39 public:
SetUp()40 void SetUp() override {
41 buffer_.reset(new FakeScatteredBuffer(kChunkSize));
42 stream_writer_.reset(new ScatteredStreamWriter(buffer_.get()));
43 }
44
TearDown()45 void TearDown() override {
46 root_messages_.clear();
47 stream_writer_.reset();
48 buffer_.reset();
49 }
50
51 protected:
52 template <class T>
CreateMessage()53 T* CreateMessage() {
54 T* message = new T();
55 root_messages_.push_back(std::unique_ptr<T>(message));
56 message->Reset(stream_writer_.get());
57 return message;
58 }
59
GetNumSerializedBytes()60 size_t GetNumSerializedBytes() {
61 return buffer_->chunks().size() * kChunkSize -
62 stream_writer_->bytes_available();
63 }
64
GetSerializedBytes(size_t start,size_t length,uint8_t * buffer)65 void GetSerializedBytes(size_t start, size_t length, uint8_t* buffer) {
66 return buffer_->GetBytes(start, length, buffer);
67 }
68
69 private:
70 std::unique_ptr<FakeScatteredBuffer> buffer_;
71 std::unique_ptr<ScatteredStreamWriter> stream_writer_;
72 std::vector<std::unique_ptr<Message>> root_messages_;
73 };
74
TEST_F(ProtoZeroConformanceTest,SimpleFieldsNoNesting)75 TEST_F(ProtoZeroConformanceTest, SimpleFieldsNoNesting) {
76 auto* msg = CreateMessage<pbtest::EveryField>();
77
78 msg->set_field_int32(-1);
79 msg->set_field_int64(-333123456789ll);
80 msg->set_field_uint32(600);
81 msg->set_field_uint64(333123456789ll);
82 msg->set_field_sint32(-5);
83 msg->set_field_sint64(-9000);
84 msg->set_field_fixed32(12345);
85 msg->set_field_fixed64(444123450000ll);
86 msg->set_field_sfixed32(-69999);
87 msg->set_field_sfixed64(-200);
88 msg->set_field_float(3.14f);
89 msg->set_field_double(0.5555);
90 msg->set_field_bool(true);
91 msg->set_small_enum(pbtest::SmallEnum::TO_BE);
92 msg->set_signed_enum(pbtest::SignedEnum::NEGATIVE);
93 msg->set_big_enum(pbtest::BigEnum::BEGIN);
94 msg->set_field_string("FizzBuzz");
95 msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"), 4);
96 msg->add_repeated_int32(1);
97 msg->add_repeated_int32(-1);
98 msg->add_repeated_int32(100);
99 msg->add_repeated_int32(2000000);
100
101 size_t msg_size = GetNumSerializedBytes();
102 EXPECT_EQ(126u, msg_size);
103
104 std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]);
105 GetSerializedBytes(0, msg_size, msg_binary.get());
106
107 pbgold::EveryField gold_msg;
108 gold_msg.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size));
109 EXPECT_EQ(-1, gold_msg.field_int32());
110 EXPECT_EQ(-333123456789ll, gold_msg.field_int64());
111 EXPECT_EQ(600u, gold_msg.field_uint32());
112 EXPECT_EQ(333123456789ull, gold_msg.field_uint64());
113 EXPECT_EQ(-5, gold_msg.field_sint32());
114 EXPECT_EQ(-9000, gold_msg.field_sint64());
115 EXPECT_EQ(12345u, gold_msg.field_fixed32());
116 EXPECT_EQ(444123450000ull, gold_msg.field_fixed64());
117 EXPECT_EQ(-69999, gold_msg.field_sfixed32());
118 EXPECT_EQ(-200, gold_msg.field_sfixed64());
119 EXPECT_FLOAT_EQ(3.14f, gold_msg.field_float());
120 EXPECT_DOUBLE_EQ(0.5555, gold_msg.field_double());
121 EXPECT_EQ(true, gold_msg.field_bool());
122 EXPECT_EQ(pbgold::SmallEnum::TO_BE, gold_msg.small_enum());
123 EXPECT_EQ(pbgold::SignedEnum::NEGATIVE, gold_msg.signed_enum());
124 EXPECT_EQ(pbgold::BigEnum::BEGIN, gold_msg.big_enum());
125 EXPECT_EQ("FizzBuzz", gold_msg.field_string());
126 EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), gold_msg.field_bytes());
127 EXPECT_EQ(4, gold_msg.repeated_int32_size());
128 EXPECT_EQ(1, gold_msg.repeated_int32(0));
129 EXPECT_EQ(-1, gold_msg.repeated_int32(1));
130 EXPECT_EQ(100, gold_msg.repeated_int32(2));
131 EXPECT_EQ(2000000, gold_msg.repeated_int32(3));
132 }
133
TEST_F(ProtoZeroConformanceTest,NestedMessages)134 TEST_F(ProtoZeroConformanceTest, NestedMessages) {
135 auto* msg_a = CreateMessage<pbtest::NestedA>();
136
137 pbtest::NestedA::NestedB* msg_b = msg_a->add_repeated_a();
138 pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->set_value_b();
139 msg_c->set_value_c(321);
140 msg_b = msg_a->add_repeated_a();
141 msg_c = msg_a->set_super_nested();
142 msg_c->set_value_c(1000);
143 msg_a->Finalize();
144
145 size_t msg_size = GetNumSerializedBytes();
146 EXPECT_EQ(26u, msg_size);
147
148 std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]);
149 GetSerializedBytes(0, msg_size, msg_binary.get());
150
151 pbgold::NestedA gold_msg_a;
152 gold_msg_a.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size));
153 EXPECT_EQ(2, gold_msg_a.repeated_a_size());
154 EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
155 EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
156 EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
157 }
158
TEST(ProtoZeroTest,Simple)159 TEST(ProtoZeroTest, Simple) {
160 // Test the includes for indirect public import: library.pbzero.h ->
161 // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h .
162 EXPECT_LE(0u, sizeof(pbtest::TrickyPublicImport));
163 }
164
TEST(ProtoZeroTest,Reflection)165 TEST(ProtoZeroTest, Reflection) {
166 // Tests camel case conversion as well.
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 const ProtoFieldDescriptor* reflection =
178 pbtest::EveryField::GetFieldDescriptor(
179 pbtest::EveryField::kFieldInt32FieldNumber);
180 EXPECT_STREQ("field_int32", reflection->name());
181 EXPECT_EQ(ProtoFieldDescriptor::Type::TYPE_INT32, reflection->type());
182 EXPECT_EQ(1u, reflection->number());
183 EXPECT_FALSE(reflection->is_repeated());
184 EXPECT_TRUE(reflection->is_valid());
185
186 EXPECT_FALSE(pbtest::TransgalacticParcel::GetFieldDescriptor(42)->is_valid());
187 }
188
189 } // namespace
190 } // namespace protozero
191