1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 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#include <google/protobuf/message.h> 36 37#include <sys/types.h> 38#include <sys/stat.h> 39#include <fcntl.h> 40#ifdef _MSC_VER 41#include <io.h> 42#else 43#include <unistd.h> 44#endif 45#include <sstream> 46#include <fstream> 47 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> 55 56#include <google/protobuf/testing/googletest.h> 57#include <gtest/gtest.h> 58 59namespace google { 60namespace protobuf { 61 62#ifndef O_BINARY 63#ifdef _O_BINARY 64#define O_BINARY _O_BINARY 65#else 66#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. 67#endif 68#endif 69 70TEST(MessageTest, SerializeHelpers) { 71 // TODO(kenton): Test more helpers? They're all two-liners so it seems 72 // like a waste of time. 73 74 protobuf_unittest::TestAllTypes message; 75 TestUtil::SetAllFields(&message); 76 stringstream stream; 77 78 string str1("foo"); 79 string str2("bar"); 80 81 EXPECT_TRUE(message.SerializeToString(&str1)); 82 EXPECT_TRUE(message.AppendToString(&str2)); 83 EXPECT_TRUE(message.SerializeToOstream(&stream)); 84 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 88 // stdout. 89 EXPECT_TRUE(str2.substr(3) == str1); 90 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); 94 95 EXPECT_TRUE(message.SerializeAsString() == str1); 96 97} 98 99TEST(MessageTest, SerializeToBrokenOstream) { 100 ofstream out; 101 protobuf_unittest::TestAllTypes message; 102 message.set_optional_int32(123); 103 104 EXPECT_FALSE(message.SerializeToOstream(&out)); 105} 106 107TEST(MessageTest, ParseFromFileDescriptor) { 108 string filename = TestSourceDir() + 109 "/google/protobuf/testdata/golden_message"; 110 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 111 112 unittest::TestAllTypes message; 113 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 114 TestUtil::ExpectAllFieldsSet(message); 115 116 EXPECT_GE(close(file), 0); 117} 118 119TEST(MessageTest, ParsePackedFromFileDescriptor) { 120 string filename = 121 TestSourceDir() + 122 "/google/protobuf/testdata/golden_packed_fields_message"; 123 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 124 125 unittest::TestPackedTypes message; 126 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 127 TestUtil::ExpectPackedFieldsSet(message); 128 129 EXPECT_GE(close(file), 0); 130} 131 132TEST(MessageTest, ParseHelpers) { 133 // TODO(kenton): Test more helpers? They're all two-liners so it seems 134 // like a waste of time. 135 string data; 136 137 { 138 // Set up. 139 protobuf_unittest::TestAllTypes message; 140 TestUtil::SetAllFields(&message); 141 message.SerializeToString(&data); 142 } 143 144 { 145 // Test ParseFromString. 146 protobuf_unittest::TestAllTypes message; 147 EXPECT_TRUE(message.ParseFromString(data)); 148 TestUtil::ExpectAllFieldsSet(message); 149 } 150 151 { 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); 158 } 159 160 { 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); 168 } 169 170 { 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; 175 EXPECT_FALSE( 176 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); 177 } 178} 179 180TEST(MessageTest, ParseFailsIfNotInitialized) { 181 unittest::TestRequired message; 182 vector<string> errors; 183 184 { 185 ScopedMemoryLog log; 186 EXPECT_FALSE(message.ParseFromString("")); 187 errors = log.GetMessages(ERROR); 188 } 189 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", 193 errors[0]); 194} 195 196TEST(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)); 201} 202 203TEST(MessageTest, InitializationErrorString) { 204 unittest::TestRequired message; 205 EXPECT_EQ("a, b, c", message.InitializationErrorString()); 206} 207 208#ifdef PROTOBUF_HAS_DEATH_TEST 209 210TEST(MessageTest, SerializeFailsIfNotInitialized) { 211 unittest::TestRequired message; 212 string data; 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"); 216} 217 218TEST(MessageTest, CheckInitialized) { 219 unittest::TestRequired message; 220 EXPECT_DEATH(message.CheckInitialized(), 221 "Message of type \"protobuf_unittest.TestRequired\" is missing required " 222 "fields: a, b, c"); 223} 224 225#endif // PROTOBUF_HAS_DEATH_TEST 226 227TEST(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)); 232} 233 234TEST(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]); 242} 243 244TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { 245 unittest::TestAllTypes message; 246 247 // Control case. 248 EXPECT_TRUE(message.ParseFromArray("", 0)); 249 250 // The byte is a valid varint, but not a valid tag (zero). 251 EXPECT_FALSE(message.ParseFromArray("\0", 1)); 252 253 // The byte is a malformed varint. 254 EXPECT_FALSE(message.ParseFromArray("\200", 1)); 255 256 // The byte is an endgroup tag, but we aren't parsing a group. 257 EXPECT_FALSE(message.ParseFromArray("\014", 1)); 258} 259 260namespace { 261 262void 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()); 266} 267 268void 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"); 276} 277 278} // namespace 279 280// Test that if an optional or required message/group field appears multiple 281// times in the input, they need to be merged. 282TEST(MessageTest, ParsingMerge) { 283 unittest::TestParsingMerge::RepeatedFieldsGenerator generator; 284 unittest::TestAllTypes* msg1; 285 unittest::TestAllTypes* msg2; 286 unittest::TestAllTypes* msg3; 287 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) 293 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); 299 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) 306 307 ASSIGN_REPEATED_GROUP(group1); 308 ASSIGN_REPEATED_GROUP(group2); 309 310#undef ASSIGN_REPEATED_GROUP 311 312 string buffer; 313 generator.SerializeToString(&buffer); 314 unittest::TestParsingMerge parsing_merge; 315 parsing_merge.ParseFromString(buffer); 316 317 // Required and optional fields should be merged. 318 ExpectMessageMerged(parsing_merge.required_all_types()); 319 ExpectMessageMerged(parsing_merge.optional_all_types()); 320 ExpectMessageMerged( 321 parsing_merge.optionalgroup().optional_group_all_types()); 322 ExpectMessageMerged( 323 parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext)); 324 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)); 330} 331 332TEST(MessageFactoryTest, GeneratedFactoryLookup) { 333 EXPECT_EQ( 334 MessageFactory::generated_factory()->GetPrototype( 335 protobuf_unittest::TestAllTypes::descriptor()), 336 &protobuf_unittest::TestAllTypes::default_instance()); 337} 338 339TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { 340 // Construct a new descriptor. 341 DescriptorPool pool; 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); 346 347 // Trying to construct it should return NULL. 348 EXPECT_TRUE( 349 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); 350} 351 352 353} // namespace protobuf 354} // namespace google 355