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@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 
DynamicMessageTest()69   DynamicMessageTest(): factory_(&pool_) {}
70 
SetUp()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 
TEST_F(DynamicMessageTest,Descriptor)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 
TEST_F(DynamicMessageTest,OnePrototype)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 
TEST_F(DynamicMessageTest,Defaults)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 
TEST_F(DynamicMessageTest,IndependentOffsets)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 
TEST_F(DynamicMessageTest,Extensions)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 
TEST_F(DynamicMessageTest,PackedFields)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 
TEST_F(DynamicMessageTest,Oneof)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 
TEST_F(DynamicMessageTest,SpaceUsed)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