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