/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <limits> #include <memory> #include <vector> #include "gtest/gtest.h" #include "perfetto/protozero/message_handle.h" #include "src/protozero/test/fake_scattered_buffer.h" // Autogenerated headers in out/*/gen/ #include "src/protozero/test/example_proto/library.pbzero.h" #include "src/protozero/test/example_proto/test_messages.pb.h" #include "src/protozero/test/example_proto/test_messages.pbzero.h" namespace pbtest = foo::bar::pbzero; // Generated by the protozero plugin. namespace pbgold = foo::bar; // Generated by the official protobuf compiler. namespace protozero { namespace { constexpr size_t kChunkSize = 42; class ProtoZeroConformanceTest : public ::testing::Test { public: void SetUp() override { buffer_.reset(new FakeScatteredBuffer(kChunkSize)); stream_writer_.reset(new ScatteredStreamWriter(buffer_.get())); } void TearDown() override { root_messages_.clear(); stream_writer_.reset(); buffer_.reset(); } protected: template <class T> T* CreateMessage() { T* message = new T(); root_messages_.push_back(std::unique_ptr<T>(message)); message->Reset(stream_writer_.get()); return message; } size_t GetNumSerializedBytes() { return buffer_->chunks().size() * kChunkSize - stream_writer_->bytes_available(); } void GetSerializedBytes(size_t start, size_t length, uint8_t* buffer) { return buffer_->GetBytes(start, length, buffer); } private: std::unique_ptr<FakeScatteredBuffer> buffer_; std::unique_ptr<ScatteredStreamWriter> stream_writer_; std::vector<std::unique_ptr<Message>> root_messages_; }; TEST_F(ProtoZeroConformanceTest, SimpleFieldsNoNesting) { auto* msg = CreateMessage<pbtest::EveryField>(); msg->set_field_int32(-1); msg->set_field_int64(-333123456789ll); msg->set_field_uint32(600); msg->set_field_uint64(333123456789ll); msg->set_field_sint32(-5); msg->set_field_sint64(-9000); msg->set_field_fixed32(12345); msg->set_field_fixed64(444123450000ll); msg->set_field_sfixed32(-69999); msg->set_field_sfixed64(-200); msg->set_field_float(3.14f); msg->set_field_double(0.5555); msg->set_field_bool(true); msg->set_small_enum(pbtest::SmallEnum::TO_BE); msg->set_signed_enum(pbtest::SignedEnum::NEGATIVE); msg->set_big_enum(pbtest::BigEnum::BEGIN); msg->set_field_string("FizzBuzz"); msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"), 4); msg->add_repeated_int32(1); msg->add_repeated_int32(-1); msg->add_repeated_int32(100); msg->add_repeated_int32(2000000); size_t msg_size = GetNumSerializedBytes(); std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]); GetSerializedBytes(0, msg_size, msg_binary.get()); pbgold::EveryField gold_msg; gold_msg.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size)); EXPECT_EQ(-1, gold_msg.field_int32()); EXPECT_EQ(-333123456789ll, gold_msg.field_int64()); EXPECT_EQ(600u, gold_msg.field_uint32()); EXPECT_EQ(333123456789ull, gold_msg.field_uint64()); EXPECT_EQ(-5, gold_msg.field_sint32()); EXPECT_EQ(-9000, gold_msg.field_sint64()); EXPECT_EQ(12345u, gold_msg.field_fixed32()); EXPECT_EQ(444123450000ull, gold_msg.field_fixed64()); EXPECT_EQ(-69999, gold_msg.field_sfixed32()); EXPECT_EQ(-200, gold_msg.field_sfixed64()); EXPECT_FLOAT_EQ(3.14f, gold_msg.field_float()); EXPECT_DOUBLE_EQ(0.5555, gold_msg.field_double()); EXPECT_EQ(true, gold_msg.field_bool()); EXPECT_EQ(pbgold::SmallEnum::TO_BE, gold_msg.small_enum()); EXPECT_EQ(pbgold::SignedEnum::NEGATIVE, gold_msg.signed_enum()); EXPECT_EQ(pbgold::BigEnum::BEGIN, gold_msg.big_enum()); EXPECT_EQ("FizzBuzz", gold_msg.field_string()); EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), gold_msg.field_bytes()); EXPECT_EQ(4, gold_msg.repeated_int32_size()); EXPECT_EQ(1, gold_msg.repeated_int32(0)); EXPECT_EQ(-1, gold_msg.repeated_int32(1)); EXPECT_EQ(100, gold_msg.repeated_int32(2)); EXPECT_EQ(2000000, gold_msg.repeated_int32(3)); EXPECT_EQ(msg_size, static_cast<size_t>(gold_msg.ByteSize())); } TEST_F(ProtoZeroConformanceTest, NestedMessages) { auto* msg_a = CreateMessage<pbtest::NestedA>(); pbtest::NestedA::NestedB* msg_b = msg_a->add_repeated_a(); pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->set_value_b(); msg_c->set_value_c(321); msg_b = msg_a->add_repeated_a(); msg_c = msg_a->set_super_nested(); msg_c->set_value_c(1000); msg_a->Finalize(); size_t msg_size = GetNumSerializedBytes(); EXPECT_EQ(26u, msg_size); std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]); GetSerializedBytes(0, msg_size, msg_binary.get()); pbgold::NestedA gold_msg_a; gold_msg_a.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size)); EXPECT_EQ(2, gold_msg_a.repeated_a_size()); EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c()); EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b()); EXPECT_EQ(1000, gold_msg_a.super_nested().value_c()); } TEST(ProtoZeroTest, Simple) { // Test the includes for indirect public import: library.pbzero.h -> // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h . EXPECT_LE(0u, sizeof(pbtest::TrickyPublicImport)); } TEST(ProtoZeroTest, FieldNumbers) { EXPECT_EQ(1, pbtest::CamelCaseFields::kFooBarBazFieldNumber); EXPECT_EQ(2, pbtest::CamelCaseFields::kBarBazFieldNumber); EXPECT_EQ(3, pbtest::CamelCaseFields::kMooMooFieldNumber); EXPECT_EQ(4, pbtest::CamelCaseFields::kURLEncoderFieldNumber); EXPECT_EQ(5, pbtest::CamelCaseFields::kXMapFieldNumber); EXPECT_EQ(6, pbtest::CamelCaseFields::kUrLENcoDerFieldNumber); EXPECT_EQ(7, pbtest::CamelCaseFields::kBigBangFieldNumber); EXPECT_EQ(8, pbtest::CamelCaseFields::kU2FieldNumber); EXPECT_EQ(9, pbtest::CamelCaseFields::kBangBigFieldNumber); } } // namespace } // namespace protozero