Home | History | Annotate | Download | only in util
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #include <google/protobuf/util/type_resolver_util.h>
     32 
     33 #include <limits>
     34 #include <memory>
     35 #ifndef _SHARED_PTR_H
     36 #include <google/protobuf/stubs/shared_ptr.h>
     37 #endif
     38 #include <string>
     39 #include <vector>
     40 
     41 #include <google/protobuf/type.pb.h>
     42 #include <google/protobuf/wrappers.pb.h>
     43 #include <google/protobuf/map_unittest.pb.h>
     44 #include <google/protobuf/test_util.h>
     45 #include <google/protobuf/unittest.pb.h>
     46 #include <google/protobuf/util/json_format_proto3.pb.h>
     47 #include <google/protobuf/util/type_resolver.h>
     48 #include <google/protobuf/testing/googletest.h>
     49 #include <gtest/gtest.h>
     50 
     51 namespace google {
     52 namespace protobuf {
     53 namespace util {
     54 namespace {
     55 using google::protobuf::Type;
     56 using google::protobuf::Enum;
     57 using google::protobuf::Field;
     58 using google::protobuf::Option;
     59 using google::protobuf::BoolValue;
     60 
     61 static const char kUrlPrefix[] = "type.googleapis.com";
     62 
     63 class DescriptorPoolTypeResolverTest : public testing::Test {
     64  public:
     65   DescriptorPoolTypeResolverTest() {
     66     resolver_.reset(NewTypeResolverForDescriptorPool(
     67         kUrlPrefix, DescriptorPool::generated_pool()));
     68   }
     69 
     70   const Field* FindField(const Type& type, const string& name) {
     71     for (int i = 0; i < type.fields_size(); ++i) {
     72       const Field& field = type.fields(i);
     73       if (field.name() == name) {
     74         return &field;
     75       }
     76     }
     77     return NULL;
     78   }
     79 
     80   bool HasField(const Type& type, const string& name) {
     81     return FindField(type, name) != NULL;
     82   }
     83 
     84   bool HasField(const Type& type, Field::Cardinality cardinality,
     85                 Field::Kind kind, const string& name, int number) {
     86     const Field* field = FindField(type, name);
     87     if (field == NULL) {
     88       return false;
     89     }
     90     return field->cardinality() == cardinality &&
     91         field->kind() == kind && field->number() == number;
     92   }
     93 
     94   bool CheckFieldTypeUrl(const Type& type, const string& name,
     95                          const string& type_url) {
     96     const Field* field = FindField(type, name);
     97     if (field == NULL) {
     98       return false;
     99     }
    100     return field->type_url() == type_url;
    101   }
    102 
    103   bool FieldInOneof(const Type& type, const string& name,
    104                     const string& oneof_name) {
    105     const Field* field = FindField(type, name);
    106     if (field == NULL || field->oneof_index() <= 0 ||
    107         field->oneof_index() > type.oneofs_size()) {
    108       return false;
    109     }
    110     return type.oneofs(field->oneof_index() - 1) == oneof_name;
    111   }
    112 
    113   bool IsPacked(const Type& type, const string& name) {
    114     const Field* field = FindField(type, name);
    115     if (field == NULL) {
    116       return false;
    117     }
    118     return field->packed();
    119   }
    120 
    121   bool EnumHasValue(const Enum& type, const string& name, int number) {
    122     for (int i = 0; i < type.enumvalue_size(); ++i) {
    123       if (type.enumvalue(i).name() == name &&
    124           type.enumvalue(i).number() == number) {
    125         return true;
    126       }
    127     }
    128     return false;
    129   }
    130 
    131   bool HasBoolOption(const RepeatedPtrField<Option>& options,
    132                      const string& name, bool value) {
    133     for (int i = 0; i < options.size(); ++i) {
    134       const Option& option = options.Get(i);
    135       if (option.name() == name) {
    136         BoolValue bool_value;
    137         if (option.value().UnpackTo(&bool_value) &&
    138             bool_value.value() == value) {
    139           return true;
    140         }
    141       }
    142     }
    143     return false;
    144   }
    145 
    146   string GetTypeUrl(string full_name) {
    147     return kUrlPrefix + string("/") + full_name;
    148   }
    149 
    150   template<typename T>
    151   string GetTypeUrl() {
    152     return GetTypeUrl(T::descriptor()->full_name());
    153   }
    154 
    155  protected:
    156   google::protobuf::scoped_ptr<TypeResolver> resolver_;
    157 };
    158 
    159 TEST_F(DescriptorPoolTypeResolverTest, TestAllTypes) {
    160   Type type;
    161   ASSERT_TRUE(resolver_->ResolveMessageType(
    162       GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
    163   // Check all optional fields.
    164   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    165                        Field::TYPE_INT32, "optional_int32", 1));
    166   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    167                        Field::TYPE_INT64, "optional_int64", 2));
    168   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    169                        Field::TYPE_UINT32, "optional_uint32", 3));
    170   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    171                        Field::TYPE_UINT64, "optional_uint64", 4));
    172   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    173                        Field::TYPE_SINT32, "optional_sint32", 5));
    174   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    175                        Field::TYPE_SINT64, "optional_sint64", 6));
    176   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    177                        Field::TYPE_FIXED32, "optional_fixed32", 7));
    178   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    179                        Field::TYPE_FIXED64, "optional_fixed64", 8));
    180   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    181                        Field::TYPE_SFIXED32, "optional_sfixed32", 9));
    182   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    183                        Field::TYPE_SFIXED64, "optional_sfixed64", 10));
    184   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    185                        Field::TYPE_FLOAT, "optional_float", 11));
    186   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    187                        Field::TYPE_DOUBLE, "optional_double", 12));
    188   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    189                        Field::TYPE_BOOL, "optional_bool", 13));
    190   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    191                        Field::TYPE_STRING, "optional_string", 14));
    192   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    193                        Field::TYPE_BYTES, "optional_bytes", 15));
    194 
    195   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    196                        Field::TYPE_MESSAGE, "optional_nested_message", 18));
    197   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    198                        Field::TYPE_MESSAGE, "optional_foreign_message", 19));
    199 
    200   EXPECT_TRUE(CheckFieldTypeUrl(
    201       type, "optional_nested_message",
    202       GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
    203   EXPECT_TRUE(CheckFieldTypeUrl(
    204       type, "optional_foreign_message",
    205       GetTypeUrl<protobuf_unittest::ForeignMessage>()));
    206 
    207   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    208                        Field::TYPE_ENUM, "optional_nested_enum", 21));
    209   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    210                        Field::TYPE_ENUM, "optional_foreign_enum", 22));
    211 
    212   EXPECT_TRUE(CheckFieldTypeUrl(
    213       type, "optional_nested_enum",
    214       GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
    215   EXPECT_TRUE(CheckFieldTypeUrl(
    216       type, "optional_foreign_enum",
    217       GetTypeUrl("protobuf_unittest.ForeignEnum")));
    218 
    219   // Check all repeated fields.
    220   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    221                        Field::TYPE_INT32, "repeated_int32", 31));
    222   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    223                        Field::TYPE_INT64, "repeated_int64", 32));
    224   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    225                        Field::TYPE_UINT32, "repeated_uint32", 33));
    226   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    227                        Field::TYPE_UINT64, "repeated_uint64", 34));
    228   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    229                        Field::TYPE_SINT32, "repeated_sint32", 35));
    230   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    231                        Field::TYPE_SINT64, "repeated_sint64", 36));
    232   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    233                        Field::TYPE_FIXED32, "repeated_fixed32", 37));
    234   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    235                        Field::TYPE_FIXED64, "repeated_fixed64", 38));
    236   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    237                        Field::TYPE_SFIXED32, "repeated_sfixed32", 39));
    238   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    239                        Field::TYPE_SFIXED64, "repeated_sfixed64", 40));
    240   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    241                        Field::TYPE_FLOAT, "repeated_float", 41));
    242   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    243                        Field::TYPE_DOUBLE, "repeated_double", 42));
    244   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    245                        Field::TYPE_BOOL, "repeated_bool", 43));
    246   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    247                        Field::TYPE_STRING, "repeated_string", 44));
    248   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    249                        Field::TYPE_BYTES, "repeated_bytes", 45));
    250 
    251   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    252                        Field::TYPE_MESSAGE, "repeated_nested_message", 48));
    253   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    254                        Field::TYPE_MESSAGE, "repeated_foreign_message", 49));
    255 
    256   EXPECT_TRUE(CheckFieldTypeUrl(
    257       type, "repeated_nested_message",
    258       GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
    259   EXPECT_TRUE(CheckFieldTypeUrl(
    260       type, "repeated_foreign_message",
    261       GetTypeUrl<protobuf_unittest::ForeignMessage>()));
    262 
    263   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    264                        Field::TYPE_ENUM, "repeated_nested_enum", 51));
    265   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    266                        Field::TYPE_ENUM, "repeated_foreign_enum", 52));
    267 
    268   EXPECT_TRUE(CheckFieldTypeUrl(
    269       type, "repeated_nested_enum",
    270       GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
    271   EXPECT_TRUE(CheckFieldTypeUrl(
    272       type, "repeated_foreign_enum",
    273       GetTypeUrl("protobuf_unittest.ForeignEnum")));
    274 
    275   // Groups are discarded when converting to Type.
    276   const Descriptor* descriptor = protobuf_unittest::TestAllTypes::descriptor();
    277   EXPECT_TRUE(descriptor->FindFieldByName("optionalgroup") != NULL);
    278   EXPECT_TRUE(descriptor->FindFieldByName("repeatedgroup") != NULL);
    279   ASSERT_FALSE(HasField(type, "optionalgroup"));
    280   ASSERT_FALSE(HasField(type, "repeatedgroup"));
    281 }
    282 
    283 TEST_F(DescriptorPoolTypeResolverTest, TestPackedField) {
    284   Type type;
    285   ASSERT_TRUE(resolver_->ResolveMessageType(
    286       GetTypeUrl<protobuf_unittest::TestPackedTypes>(), &type).ok());
    287   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    288                        Field::TYPE_INT32, "packed_int32", 90));
    289   EXPECT_TRUE(IsPacked(type, "packed_int32"));
    290 }
    291 
    292 TEST_F(DescriptorPoolTypeResolverTest, TestOneof) {
    293   Type type;
    294   ASSERT_TRUE(resolver_->ResolveMessageType(
    295       GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
    296   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    297                        Field::TYPE_UINT32, "oneof_uint32", 111));
    298   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    299                        Field::TYPE_MESSAGE, "oneof_nested_message", 112));
    300   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    301                        Field::TYPE_STRING, "oneof_string", 113));
    302   EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
    303                        Field::TYPE_BYTES, "oneof_bytes", 114));
    304   EXPECT_TRUE(FieldInOneof(type, "oneof_uint32", "oneof_field"));
    305   EXPECT_TRUE(FieldInOneof(type, "oneof_nested_message", "oneof_field"));
    306   EXPECT_TRUE(FieldInOneof(type, "oneof_string", "oneof_field"));
    307   EXPECT_TRUE(FieldInOneof(type, "oneof_bytes", "oneof_field"));
    308 }
    309 
    310 TEST_F(DescriptorPoolTypeResolverTest, TestMap) {
    311   Type type;
    312   ASSERT_TRUE(resolver_->ResolveMessageType(
    313       GetTypeUrl<protobuf_unittest::TestMap>(), &type).ok());
    314   EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
    315                        Field::TYPE_MESSAGE, "map_int32_int32", 1));
    316   EXPECT_TRUE(CheckFieldTypeUrl(
    317       type, "map_int32_int32",
    318       GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry")));
    319 
    320   ASSERT_TRUE(resolver_->ResolveMessageType(
    321       GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry"),
    322       &type).ok());
    323   EXPECT_TRUE(HasBoolOption(type.options(), "map_entry", true));
    324 }
    325 
    326 TEST_F(DescriptorPoolTypeResolverTest, TestEnum) {
    327   Enum type;
    328   ASSERT_TRUE(resolver_->ResolveEnumType(
    329       GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"), &type).ok());
    330   EnumHasValue(type, "FOO", 1);
    331   EnumHasValue(type, "BAR", 2);
    332   EnumHasValue(type, "BAZ", 3);
    333   EnumHasValue(type, "NEG", -1);
    334 }
    335 
    336 TEST_F(DescriptorPoolTypeResolverTest, TestJsonName) {
    337   Type type;
    338   ASSERT_TRUE(resolver_->ResolveMessageType(
    339                            GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type)
    340                   .ok());
    341   EXPECT_EQ("optionalInt32", FindField(type, "optional_int32")->json_name());
    342 
    343   ASSERT_TRUE(resolver_->ResolveMessageType(
    344                            GetTypeUrl<proto3::TestCustomJsonName>(), &type)
    345                   .ok());
    346   EXPECT_EQ("@value", FindField(type, "value")->json_name());
    347 }
    348 
    349 }  // namespace
    350 }  // namespace util
    351 }  // namespace protobuf
    352 }  // namespace google
    353