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 // Author: kenton (at) google.com (Kenton Varda) 32 // Based on original Protocol Buffers design by 33 // Sanjay Ghemawat, Jeff Dean, and others. 34 // 35 // Since the reflection interface for DynamicMessage is implemented by 36 // GenericMessageReflection, the only thing we really have to test is 37 // that DynamicMessage correctly sets up the information that 38 // GenericMessageReflection needs to use. So, we focus on that in this 39 // test. Other tests, such as generic_message_reflection_unittest and 40 // reflection_ops_unittest, cover the rest of the functionality used by 41 // DynamicMessage. 42 43 #include <memory> 44 #ifndef _SHARED_PTR_H 45 #include <google/protobuf/stubs/shared_ptr.h> 46 #endif 47 48 #include <google/protobuf/stubs/scoped_ptr.h> 49 #include <google/protobuf/stubs/common.h> 50 #include <google/protobuf/dynamic_message.h> 51 #include <google/protobuf/descriptor.h> 52 #include <google/protobuf/descriptor.pb.h> 53 #include <google/protobuf/test_util.h> 54 #include <google/protobuf/unittest.pb.h> 55 #include <google/protobuf/unittest_no_field_presence.pb.h> 56 57 #include <google/protobuf/stubs/logging.h> 58 #include <google/protobuf/testing/googletest.h> 59 #include <gtest/gtest.h> 60 61 namespace google { 62 namespace protobuf { 63 64 class DynamicMessageTest : public testing::Test { 65 protected: 66 DescriptorPool pool_; 67 DynamicMessageFactory factory_; 68 const Descriptor* descriptor_; 69 const Message* prototype_; 70 const Descriptor* extensions_descriptor_; 71 const Message* extensions_prototype_; 72 const Descriptor* packed_descriptor_; 73 const Message* packed_prototype_; 74 const Descriptor* oneof_descriptor_; 75 const Message* oneof_prototype_; 76 const Descriptor* proto3_descriptor_; 77 const Message* proto3_prototype_; 78 79 DynamicMessageTest(): factory_(&pool_) {} 80 81 virtual void SetUp() { 82 // We want to make sure that DynamicMessage works (particularly with 83 // extensions) even if we use descriptors that are *not* from compiled-in 84 // types, so we make copies of the descriptors for unittest.proto and 85 // unittest_import.proto. 86 FileDescriptorProto unittest_file; 87 FileDescriptorProto unittest_import_file; 88 FileDescriptorProto unittest_import_public_file; 89 FileDescriptorProto unittest_no_field_presence_file; 90 91 unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); 92 unittest_import::ImportMessage::descriptor()->file()->CopyTo( 93 &unittest_import_file); 94 unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( 95 &unittest_import_public_file); 96 proto2_nofieldpresence_unittest::TestAllTypes::descriptor()-> 97 file()->CopyTo(&unittest_no_field_presence_file); 98 99 ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); 100 ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); 101 ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL); 102 ASSERT_TRUE(pool_.BuildFile(unittest_no_field_presence_file) != NULL); 103 104 descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes"); 105 ASSERT_TRUE(descriptor_ != NULL); 106 prototype_ = factory_.GetPrototype(descriptor_); 107 108 extensions_descriptor_ = 109 pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions"); 110 ASSERT_TRUE(extensions_descriptor_ != NULL); 111 extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_); 112 113 packed_descriptor_ = 114 pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); 115 ASSERT_TRUE(packed_descriptor_ != NULL); 116 packed_prototype_ = factory_.GetPrototype(packed_descriptor_); 117 118 oneof_descriptor_ = 119 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); 120 ASSERT_TRUE(oneof_descriptor_ != NULL); 121 oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); 122 123 proto3_descriptor_ = 124 pool_.FindMessageTypeByName( 125 "proto2_nofieldpresence_unittest.TestAllTypes"); 126 ASSERT_TRUE(proto3_descriptor_ != NULL); 127 proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_); 128 } 129 }; 130 131 TEST_F(DynamicMessageTest, Descriptor) { 132 // Check that the descriptor on the DynamicMessage matches the descriptor 133 // passed to GetPrototype(). 134 EXPECT_EQ(prototype_->GetDescriptor(), descriptor_); 135 } 136 137 TEST_F(DynamicMessageTest, OnePrototype) { 138 // Check that requesting the same prototype twice produces the same object. 139 EXPECT_EQ(prototype_, factory_.GetPrototype(descriptor_)); 140 } 141 142 TEST_F(DynamicMessageTest, Defaults) { 143 // Check that all default values are set correctly in the initial message. 144 TestUtil::ReflectionTester reflection_tester(descriptor_); 145 reflection_tester.ExpectClearViaReflection(*prototype_); 146 } 147 148 TEST_F(DynamicMessageTest, IndependentOffsets) { 149 // Check that all fields have independent offsets by setting each 150 // one to a unique value then checking that they all still have those 151 // unique values (i.e. they don't stomp each other). 152 google::protobuf::scoped_ptr<Message> message(prototype_->New()); 153 TestUtil::ReflectionTester reflection_tester(descriptor_); 154 155 reflection_tester.SetAllFieldsViaReflection(message.get()); 156 reflection_tester.ExpectAllFieldsSetViaReflection(*message); 157 } 158 159 TEST_F(DynamicMessageTest, Extensions) { 160 // Check that extensions work. 161 google::protobuf::scoped_ptr<Message> message(extensions_prototype_->New()); 162 TestUtil::ReflectionTester reflection_tester(extensions_descriptor_); 163 164 reflection_tester.SetAllFieldsViaReflection(message.get()); 165 reflection_tester.ExpectAllFieldsSetViaReflection(*message); 166 } 167 168 TEST_F(DynamicMessageTest, PackedFields) { 169 // Check that packed fields work properly. 170 google::protobuf::scoped_ptr<Message> message(packed_prototype_->New()); 171 TestUtil::ReflectionTester reflection_tester(packed_descriptor_); 172 173 reflection_tester.SetPackedFieldsViaReflection(message.get()); 174 reflection_tester.ExpectPackedFieldsSetViaReflection(*message); 175 } 176 177 TEST_F(DynamicMessageTest, Oneof) { 178 // Check that oneof fields work properly. 179 google::protobuf::scoped_ptr<Message> message(oneof_prototype_->New()); 180 181 // Check default values. 182 const Descriptor* descriptor = message->GetDescriptor(); 183 const Reflection* reflection = message->GetReflection(); 184 EXPECT_EQ(0, reflection->GetInt32( 185 *message, descriptor->FindFieldByName("foo_int"))); 186 EXPECT_EQ("", reflection->GetString( 187 *message, descriptor->FindFieldByName("foo_string"))); 188 EXPECT_EQ("", reflection->GetString( 189 *message, descriptor->FindFieldByName("foo_cord"))); 190 EXPECT_EQ("", reflection->GetString( 191 *message, descriptor->FindFieldByName("foo_string_piece"))); 192 EXPECT_EQ("", reflection->GetString( 193 *message, descriptor->FindFieldByName("foo_bytes"))); 194 EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( 195 *message, descriptor->FindFieldByName("foo_enum"))->number()); 196 const Descriptor* nested_descriptor; 197 const Message* nested_prototype; 198 nested_descriptor = 199 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage"); 200 nested_prototype = factory_.GetPrototype(nested_descriptor); 201 EXPECT_EQ(nested_prototype, 202 &reflection->GetMessage( 203 *message, descriptor->FindFieldByName("foo_message"))); 204 const Descriptor* foogroup_descriptor; 205 const Message* foogroup_prototype; 206 foogroup_descriptor = 207 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup"); 208 foogroup_prototype = factory_.GetPrototype(foogroup_descriptor); 209 EXPECT_EQ(foogroup_prototype, 210 &reflection->GetMessage( 211 *message, descriptor->FindFieldByName("foogroup"))); 212 EXPECT_NE(foogroup_prototype, 213 &reflection->GetMessage( 214 *message, descriptor->FindFieldByName("foo_lazy_message"))); 215 EXPECT_EQ(5, reflection->GetInt32( 216 *message, descriptor->FindFieldByName("bar_int"))); 217 EXPECT_EQ("STRING", reflection->GetString( 218 *message, descriptor->FindFieldByName("bar_string"))); 219 EXPECT_EQ("CORD", reflection->GetString( 220 *message, descriptor->FindFieldByName("bar_cord"))); 221 EXPECT_EQ("SPIECE", reflection->GetString( 222 *message, descriptor->FindFieldByName("bar_string_piece"))); 223 EXPECT_EQ("BYTES", reflection->GetString( 224 *message, descriptor->FindFieldByName("bar_bytes"))); 225 EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( 226 *message, descriptor->FindFieldByName("bar_enum"))->number()); 227 228 // Check set functions. 229 TestUtil::ReflectionTester reflection_tester(oneof_descriptor_); 230 reflection_tester.SetOneofViaReflection(message.get()); 231 reflection_tester.ExpectOneofSetViaReflection(*message); 232 } 233 234 TEST_F(DynamicMessageTest, SpaceUsed) { 235 // Test that SpaceUsed() works properly 236 237 // Since we share the implementation with generated messages, we don't need 238 // to test very much here. Just make sure it appears to be working. 239 240 google::protobuf::scoped_ptr<Message> message(prototype_->New()); 241 TestUtil::ReflectionTester reflection_tester(descriptor_); 242 243 int initial_space_used = message->SpaceUsed(); 244 245 reflection_tester.SetAllFieldsViaReflection(message.get()); 246 EXPECT_LT(initial_space_used, message->SpaceUsed()); 247 } 248 249 TEST_F(DynamicMessageTest, Arena) { 250 Arena arena; 251 Message* message = prototype_->New(&arena); 252 (void)message; // avoid unused-variable error. 253 // Return without freeing: should not leak. 254 } 255 256 TEST_F(DynamicMessageTest, Proto3) { 257 Message* message = proto3_prototype_->New(); 258 const Reflection* refl = message->GetReflection(); 259 const Descriptor* desc = message->GetDescriptor(); 260 261 // Just test a single primtive and single message field here to make sure we 262 // are getting the no-field-presence semantics elsewhere. DynamicMessage uses 263 // GeneratedMessageReflection under the hood, so the rest should be fine as 264 // long as GMR recognizes that we're using a proto3 message. 265 const FieldDescriptor* optional_int32 = 266 desc->FindFieldByName("optional_int32"); 267 const FieldDescriptor* optional_msg = 268 desc->FindFieldByName("optional_nested_message"); 269 EXPECT_TRUE(optional_int32 != NULL); 270 EXPECT_TRUE(optional_msg != NULL); 271 272 EXPECT_EQ(false, refl->HasField(*message, optional_int32)); 273 refl->SetInt32(message, optional_int32, 42); 274 EXPECT_EQ(true, refl->HasField(*message, optional_int32)); 275 refl->SetInt32(message, optional_int32, 0); 276 EXPECT_EQ(false, refl->HasField(*message, optional_int32)); 277 278 EXPECT_EQ(false, refl->HasField(*message, optional_msg)); 279 refl->MutableMessage(message, optional_msg); 280 EXPECT_EQ(true, refl->HasField(*message, optional_msg)); 281 delete refl->ReleaseMessage(message, optional_msg); 282 EXPECT_EQ(false, refl->HasField(*message, optional_msg)); 283 284 // Also ensure that the default instance handles field presence properly. 285 EXPECT_EQ(false, refl->HasField(*proto3_prototype_, optional_msg)); 286 287 delete message; 288 } 289 290 291 } // namespace protobuf 292 } // namespace google 293