1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
35 #include <google/protobuf/message.h>
37 #include <sys/types.h>
48 #include <google/protobuf/stubs/common.h>
49 #include <google/protobuf/io/zero_copy_stream_impl.h>
50 #include <google/protobuf/io/coded_stream.h>
51 #include <google/protobuf/descriptor.h>
52 #include <google/protobuf/descriptor.pb.h>
53 #include <google/protobuf/unittest.pb.h>
54 #include <google/protobuf/test_util.h>
56 #include <google/protobuf/testing/googletest.h>
57 #include <gtest/gtest.h>
64 #define O_BINARY _O_BINARY
66 #define O_BINARY 0 // If this isn't defined, the platform doesn't need it.
70 TEST(MessageTest, SerializeHelpers) {
71 // TODO(kenton): Test more helpers? They're all two-liners so it seems
72 // like a waste of time.
74 protobuf_unittest::TestAllTypes message;
75 TestUtil::SetAllFields(&message);
81 EXPECT_TRUE(message.SerializeToString(&str1));
82 EXPECT_TRUE(message.AppendToString(&str2));
83 EXPECT_TRUE(message.SerializeToOstream(&stream));
85 EXPECT_EQ(str1.size() + 3, str2.size());
86 EXPECT_EQ("bar", str2.substr(0, 3));
87 // Don't use EXPECT_EQ because we don't want to dump raw binary data to
89 EXPECT_TRUE(str2.substr(3) == str1);
91 // GCC gives some sort of error if we try to just do stream.str() == str1.
92 string temp = stream.str();
93 EXPECT_TRUE(temp == str1);
95 EXPECT_TRUE(message.SerializeAsString() == str1);
99 TEST(MessageTest, SerializeToBrokenOstream) {
101 protobuf_unittest::TestAllTypes message;
102 message.set_optional_int32(123);
104 EXPECT_FALSE(message.SerializeToOstream(&out));
107 TEST(MessageTest, ParseFromFileDescriptor) {
108 string filename = TestSourceDir() +
109 "/google/protobuf/testdata/golden_message";
110 int file = open(filename.c_str(), O_RDONLY | O_BINARY);
112 unittest::TestAllTypes message;
113 EXPECT_TRUE(message.ParseFromFileDescriptor(file));
114 TestUtil::ExpectAllFieldsSet(message);
116 EXPECT_GE(close(file), 0);
119 TEST(MessageTest, ParsePackedFromFileDescriptor) {
122 "/google/protobuf/testdata/golden_packed_fields_message";
123 int file = open(filename.c_str(), O_RDONLY | O_BINARY);
125 unittest::TestPackedTypes message;
126 EXPECT_TRUE(message.ParseFromFileDescriptor(file));
127 TestUtil::ExpectPackedFieldsSet(message);
129 EXPECT_GE(close(file), 0);
132 TEST(MessageTest, ParseHelpers) {
133 // TODO(kenton): Test more helpers? They're all two-liners so it seems
134 // like a waste of time.
139 protobuf_unittest::TestAllTypes message;
140 TestUtil::SetAllFields(&message);
141 message.SerializeToString(&data);
145 // Test ParseFromString.
146 protobuf_unittest::TestAllTypes message;
147 EXPECT_TRUE(message.ParseFromString(data));
148 TestUtil::ExpectAllFieldsSet(message);
152 // Test ParseFromIstream.
153 protobuf_unittest::TestAllTypes message;
154 stringstream stream(data);
155 EXPECT_TRUE(message.ParseFromIstream(&stream));
156 EXPECT_TRUE(stream.eof());
157 TestUtil::ExpectAllFieldsSet(message);
161 // Test ParseFromBoundedZeroCopyStream.
162 string data_with_junk(data);
163 data_with_junk.append("some junk on the end");
164 io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size());
165 protobuf_unittest::TestAllTypes message;
166 EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size()));
167 TestUtil::ExpectAllFieldsSet(message);
171 // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if
172 // EOF is reached before the expected number of bytes.
173 io::ArrayInputStream stream(data.data(), data.size());
174 protobuf_unittest::TestAllTypes message;
176 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1));
180 TEST(MessageTest, ParseFailsIfNotInitialized) {
181 unittest::TestRequired message;
182 vector<string> errors;
186 EXPECT_FALSE(message.ParseFromString(""));
187 errors = log.GetMessages(ERROR);
190 ASSERT_EQ(1, errors.size());
191 EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" "
192 "because it is missing required fields: a, b, c",
196 TEST(MessageTest, BypassInitializationCheckOnParse) {
197 unittest::TestRequired message;
198 io::ArrayInputStream raw_input(NULL, 0);
199 io::CodedInputStream input(&raw_input);
200 EXPECT_TRUE(message.MergePartialFromCodedStream(&input));
203 TEST(MessageTest, InitializationErrorString) {
204 unittest::TestRequired message;
205 EXPECT_EQ("a, b, c", message.InitializationErrorString());
208 #ifdef PROTOBUF_HAS_DEATH_TEST
210 TEST(MessageTest, SerializeFailsIfNotInitialized) {
211 unittest::TestRequired message;
213 EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)),
214 "Can't serialize message of type \"protobuf_unittest.TestRequired\" because "
215 "it is missing required fields: a, b, c");
218 TEST(MessageTest, CheckInitialized) {
219 unittest::TestRequired message;
220 EXPECT_DEATH(message.CheckInitialized(),
221 "Message of type \"protobuf_unittest.TestRequired\" is missing required "
225 #endif // PROTOBUF_HAS_DEATH_TEST
227 TEST(MessageTest, BypassInitializationCheckOnSerialize) {
228 unittest::TestRequired message;
229 io::ArrayOutputStream raw_output(NULL, 0);
230 io::CodedOutputStream output(&raw_output);
231 EXPECT_TRUE(message.SerializePartialToCodedStream(&output));
234 TEST(MessageTest, FindInitializationErrors) {
235 unittest::TestRequired message;
236 vector<string> errors;
237 message.FindInitializationErrors(&errors);
238 ASSERT_EQ(3, errors.size());
239 EXPECT_EQ("a", errors[0]);
240 EXPECT_EQ("b", errors[1]);
241 EXPECT_EQ("c", errors[2]);
244 TEST(MessageTest, ParseFailsOnInvalidMessageEnd) {
245 unittest::TestAllTypes message;
248 EXPECT_TRUE(message.ParseFromArray("", 0));
250 // The byte is a valid varint, but not a valid tag (zero).
251 EXPECT_FALSE(message.ParseFromArray("\0", 1));
253 // The byte is a malformed varint.
254 EXPECT_FALSE(message.ParseFromArray("\200", 1));
256 // The byte is an endgroup tag, but we aren't parsing a group.
257 EXPECT_FALSE(message.ParseFromArray("\014", 1));
262 void ExpectMessageMerged(const unittest::TestAllTypes& message) {
263 EXPECT_EQ(3, message.optional_int32());
264 EXPECT_EQ(2, message.optional_int64());
265 EXPECT_EQ("hello", message.optional_string());
268 void AssignParsingMergeMessages(
269 unittest::TestAllTypes* msg1,
270 unittest::TestAllTypes* msg2,
271 unittest::TestAllTypes* msg3) {
272 msg1->set_optional_int32(1);
273 msg2->set_optional_int64(2);
274 msg3->set_optional_int32(3);
275 msg3->set_optional_string("hello");
280 // Test that if an optional or required message/group field appears multiple
281 // times in the input, they need to be merged.
282 TEST(MessageTest, ParsingMerge) {
283 unittest::TestParsingMerge::RepeatedFieldsGenerator generator;
284 unittest::TestAllTypes* msg1;
285 unittest::TestAllTypes* msg2;
286 unittest::TestAllTypes* msg3;
288 #define ASSIGN_REPEATED_FIELD(FIELD) \
289 msg1 = generator.add_##FIELD(); \
290 msg2 = generator.add_##FIELD(); \
291 msg3 = generator.add_##FIELD(); \
292 AssignParsingMergeMessages(msg1, msg2, msg3)
294 ASSIGN_REPEATED_FIELD(field1);
295 ASSIGN_REPEATED_FIELD(field2);
296 ASSIGN_REPEATED_FIELD(field3);
297 ASSIGN_REPEATED_FIELD(ext1);
298 ASSIGN_REPEATED_FIELD(ext2);
300 #undef ASSIGN_REPEATED_FIELD
301 #define ASSIGN_REPEATED_GROUP(FIELD) \
302 msg1 = generator.add_##FIELD()->mutable_field1(); \
303 msg2 = generator.add_##FIELD()->mutable_field1(); \
304 msg3 = generator.add_##FIELD()->mutable_field1(); \
305 AssignParsingMergeMessages(msg1, msg2, msg3)
307 ASSIGN_REPEATED_GROUP(group1);
308 ASSIGN_REPEATED_GROUP(group2);
310 #undef ASSIGN_REPEATED_GROUP
313 generator.SerializeToString(&buffer);
314 unittest::TestParsingMerge parsing_merge;
315 parsing_merge.ParseFromString(buffer);
317 // Required and optional fields should be merged.
318 ExpectMessageMerged(parsing_merge.required_all_types());
319 ExpectMessageMerged(parsing_merge.optional_all_types());
321 parsing_merge.optionalgroup().optional_group_all_types());
323 parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext));
325 // Repeated fields should not be merged.
326 EXPECT_EQ(3, parsing_merge.repeated_all_types_size());
327 EXPECT_EQ(3, parsing_merge.repeatedgroup_size());
328 EXPECT_EQ(3, parsing_merge.ExtensionSize(
329 unittest::TestParsingMerge::repeated_ext));
332 TEST(MessageFactoryTest, GeneratedFactoryLookup) {
334 MessageFactory::generated_factory()->GetPrototype(
335 protobuf_unittest::TestAllTypes::descriptor()),
336 &protobuf_unittest::TestAllTypes::default_instance());
339 TEST(MessageFactoryTest, GeneratedFactoryUnknownType) {
340 // Construct a new descriptor.
342 FileDescriptorProto file;
343 file.set_name("foo.proto");
344 file.add_message_type()->set_name("Foo");
345 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0);
347 // Trying to construct it should return NULL.
349 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL);
353 } // namespace protobuf
354 } // namespace google