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 <google/protobuf/stubs/common.h> 44 #include <google/protobuf/dynamic_message.h> 45 #include <google/protobuf/descriptor.h> 46 #include <google/protobuf/descriptor.pb.h> 47 #include <google/protobuf/test_util.h> 48 #include <google/protobuf/unittest.pb.h> 49 50 #include <google/protobuf/testing/googletest.h> 51 #include <gtest/gtest.h> 52 53 namespace google { 54 namespace protobuf { 55 56 class DynamicMessageTest : public testing::Test { 57 protected: 58 DescriptorPool pool_; 59 DynamicMessageFactory factory_; 60 const Descriptor* descriptor_; 61 const Message* prototype_; 62 const Descriptor* extensions_descriptor_; 63 const Message* extensions_prototype_; 64 const Descriptor* packed_descriptor_; 65 const Message* packed_prototype_; 66 const Descriptor* oneof_descriptor_; 67 const Message* oneof_prototype_; 68 69 DynamicMessageTest(): factory_(&pool_) {} 70 71 virtual void SetUp() { 72 // We want to make sure that DynamicMessage works (particularly with 73 // extensions) even if we use descriptors that are *not* from compiled-in 74 // types, so we make copies of the descriptors for unittest.proto and 75 // unittest_import.proto. 76 FileDescriptorProto unittest_file; 77 FileDescriptorProto unittest_import_file; 78 FileDescriptorProto unittest_import_public_file; 79 80 unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); 81 unittest_import::ImportMessage::descriptor()->file()->CopyTo( 82 &unittest_import_file); 83 unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( 84 &unittest_import_public_file); 85 86 ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); 87 ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); 88 ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL); 89 90 descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes"); 91 ASSERT_TRUE(descriptor_ != NULL); 92 prototype_ = factory_.GetPrototype(descriptor_); 93 94 extensions_descriptor_ = 95 pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions"); 96 ASSERT_TRUE(extensions_descriptor_ != NULL); 97 extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_); 98 99 packed_descriptor_ = 100 pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); 101 ASSERT_TRUE(packed_descriptor_ != NULL); 102 packed_prototype_ = factory_.GetPrototype(packed_descriptor_); 103 104 oneof_descriptor_ = 105 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); 106 ASSERT_TRUE(oneof_descriptor_ != NULL); 107 oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); 108 } 109 }; 110 111 TEST_F(DynamicMessageTest, Descriptor) { 112 // Check that the descriptor on the DynamicMessage matches the descriptor 113 // passed to GetPrototype(). 114 EXPECT_EQ(prototype_->GetDescriptor(), descriptor_); 115 } 116 117 TEST_F(DynamicMessageTest, OnePrototype) { 118 // Check that requesting the same prototype twice produces the same object. 119 EXPECT_EQ(prototype_, factory_.GetPrototype(descriptor_)); 120 } 121 122 TEST_F(DynamicMessageTest, Defaults) { 123 // Check that all default values are set correctly in the initial message. 124 TestUtil::ReflectionTester reflection_tester(descriptor_); 125 reflection_tester.ExpectClearViaReflection(*prototype_); 126 } 127 128 TEST_F(DynamicMessageTest, IndependentOffsets) { 129 // Check that all fields have independent offsets by setting each 130 // one to a unique value then checking that they all still have those 131 // unique values (i.e. they don't stomp each other). 132 scoped_ptr<Message> message(prototype_->New()); 133 TestUtil::ReflectionTester reflection_tester(descriptor_); 134 135 reflection_tester.SetAllFieldsViaReflection(message.get()); 136 reflection_tester.ExpectAllFieldsSetViaReflection(*message); 137 } 138 139 TEST_F(DynamicMessageTest, Extensions) { 140 // Check that extensions work. 141 scoped_ptr<Message> message(extensions_prototype_->New()); 142 TestUtil::ReflectionTester reflection_tester(extensions_descriptor_); 143 144 reflection_tester.SetAllFieldsViaReflection(message.get()); 145 reflection_tester.ExpectAllFieldsSetViaReflection(*message); 146 } 147 148 TEST_F(DynamicMessageTest, PackedFields) { 149 // Check that packed fields work properly. 150 scoped_ptr<Message> message(packed_prototype_->New()); 151 TestUtil::ReflectionTester reflection_tester(packed_descriptor_); 152 153 reflection_tester.SetPackedFieldsViaReflection(message.get()); 154 reflection_tester.ExpectPackedFieldsSetViaReflection(*message); 155 } 156 157 TEST_F(DynamicMessageTest, Oneof) { 158 // Check that oneof fields work properly. 159 scoped_ptr<Message> message(oneof_prototype_->New()); 160 161 // Check default values. 162 const Descriptor* descriptor = message->GetDescriptor(); 163 const Reflection* reflection = message->GetReflection(); 164 EXPECT_EQ(0, reflection->GetInt32( 165 *message, descriptor->FindFieldByName("foo_int"))); 166 EXPECT_EQ("", reflection->GetString( 167 *message, descriptor->FindFieldByName("foo_string"))); 168 EXPECT_EQ("", reflection->GetString( 169 *message, descriptor->FindFieldByName("foo_cord"))); 170 EXPECT_EQ("", reflection->GetString( 171 *message, descriptor->FindFieldByName("foo_string_piece"))); 172 EXPECT_EQ("", reflection->GetString( 173 *message, descriptor->FindFieldByName("foo_bytes"))); 174 EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( 175 *message, descriptor->FindFieldByName("foo_enum"))->number()); 176 const Descriptor* nested_descriptor; 177 const Message* nested_prototype; 178 nested_descriptor = 179 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage"); 180 nested_prototype = factory_.GetPrototype(nested_descriptor); 181 EXPECT_EQ(nested_prototype, 182 &reflection->GetMessage( 183 *message, descriptor->FindFieldByName("foo_message"))); 184 const Descriptor* foogroup_descriptor; 185 const Message* foogroup_prototype; 186 foogroup_descriptor = 187 pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup"); 188 foogroup_prototype = factory_.GetPrototype(foogroup_descriptor); 189 EXPECT_EQ(foogroup_prototype, 190 &reflection->GetMessage( 191 *message, descriptor->FindFieldByName("foogroup"))); 192 EXPECT_NE(foogroup_prototype, 193 &reflection->GetMessage( 194 *message, descriptor->FindFieldByName("foo_lazy_message"))); 195 EXPECT_EQ(5, reflection->GetInt32( 196 *message, descriptor->FindFieldByName("bar_int"))); 197 EXPECT_EQ("STRING", reflection->GetString( 198 *message, descriptor->FindFieldByName("bar_string"))); 199 EXPECT_EQ("CORD", reflection->GetString( 200 *message, descriptor->FindFieldByName("bar_cord"))); 201 EXPECT_EQ("SPIECE", reflection->GetString( 202 *message, descriptor->FindFieldByName("bar_string_piece"))); 203 EXPECT_EQ("BYTES", reflection->GetString( 204 *message, descriptor->FindFieldByName("bar_bytes"))); 205 EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( 206 *message, descriptor->FindFieldByName("bar_enum"))->number()); 207 208 // Check set functions. 209 TestUtil::ReflectionTester reflection_tester(oneof_descriptor_); 210 reflection_tester.SetOneofViaReflection(message.get()); 211 reflection_tester.ExpectOneofSetViaReflection(*message); 212 } 213 214 TEST_F(DynamicMessageTest, SpaceUsed) { 215 // Test that SpaceUsed() works properly 216 217 // Since we share the implementation with generated messages, we don't need 218 // to test very much here. Just make sure it appears to be working. 219 220 scoped_ptr<Message> message(prototype_->New()); 221 TestUtil::ReflectionTester reflection_tester(descriptor_); 222 223 int initial_space_used = message->SpaceUsed(); 224 225 reflection_tester.SetAllFieldsViaReflection(message.get()); 226 EXPECT_LT(initial_space_used, message->SpaceUsed()); 227 } 228 229 } // namespace protobuf 230 } // namespace google 231