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: 40 void SetUp() override { 41 buffer_.reset(new FakeScatteredBuffer(kChunkSize)); 42 stream_writer_.reset(new ScatteredStreamWriter(buffer_.get())); 43 } 44 45 void TearDown() override { 46 root_messages_.clear(); 47 stream_writer_.reset(); 48 buffer_.reset(); 49 } 50 51 protected: 52 template <class T> 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 60 size_t GetNumSerializedBytes() { 61 return buffer_->chunks().size() * kChunkSize - 62 stream_writer_->bytes_available(); 63 } 64 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 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 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 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 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