message_unittest.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
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 47#include <google/protobuf/stubs/common.h> 48#include <google/protobuf/io/zero_copy_stream_impl.h> 49#include <google/protobuf/io/coded_stream.h> 50#include <google/protobuf/descriptor.h> 51#include <google/protobuf/descriptor.pb.h> 52#include <google/protobuf/unittest.pb.h> 53#include <google/protobuf/test_util.h> 54 55#include <google/protobuf/testing/googletest.h> 56#include <gtest/gtest.h> 57 58namespace google { 59namespace protobuf { 60 61#ifndef O_BINARY 62#ifdef _O_BINARY 63#define O_BINARY _O_BINARY 64#else 65#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. 66#endif 67#endif 68 69TEST(MessageTest, SerializeHelpers) { 70 // TODO(kenton): Test more helpers? They're all two-liners so it seems 71 // like a waste of time. 72 73 protobuf_unittest::TestAllTypes message; 74 TestUtil::SetAllFields(&message); 75 stringstream stream; 76 77 string str1("foo"); 78 string str2("bar"); 79 80 message.SerializeToString(&str1); 81 message.AppendToString(&str2); 82 message.SerializeToOstream(&stream); 83 84 EXPECT_EQ(str1.size() + 3, str2.size()); 85 EXPECT_EQ("bar", str2.substr(0, 3)); 86 // Don't use EXPECT_EQ because we don't want to dump raw binary data to 87 // stdout. 88 EXPECT_TRUE(str2.substr(3) == str1); 89 90 // GCC gives some sort of error if we try to just do stream.str() == str1. 91 string temp = stream.str(); 92 EXPECT_TRUE(temp == str1); 93 94 EXPECT_TRUE(message.SerializeAsString() == str1); 95 96} 97 98TEST(MessageTest, ParseFromFileDescriptor) { 99 string filename = TestSourceDir() + 100 "/google/protobuf/testdata/golden_message"; 101 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 102 103 unittest::TestAllTypes message; 104 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 105 TestUtil::ExpectAllFieldsSet(message); 106 107 EXPECT_GE(close(file), 0); 108} 109 110TEST(MessageTest, ParsePackedFromFileDescriptor) { 111 string filename = 112 TestSourceDir() + 113 "/google/protobuf/testdata/golden_packed_fields_message"; 114 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 115 116 unittest::TestPackedTypes message; 117 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 118 TestUtil::ExpectPackedFieldsSet(message); 119 120 EXPECT_GE(close(file), 0); 121} 122 123TEST(MessageTest, ParseHelpers) { 124 // TODO(kenton): Test more helpers? They're all two-liners so it seems 125 // like a waste of time. 126 string data; 127 128 { 129 // Set up. 130 protobuf_unittest::TestAllTypes message; 131 TestUtil::SetAllFields(&message); 132 message.SerializeToString(&data); 133 } 134 135 { 136 // Test ParseFromString. 137 protobuf_unittest::TestAllTypes message; 138 EXPECT_TRUE(message.ParseFromString(data)); 139 TestUtil::ExpectAllFieldsSet(message); 140 } 141 142 { 143 // Test ParseFromIstream. 144 protobuf_unittest::TestAllTypes message; 145 stringstream stream(data); 146 EXPECT_TRUE(message.ParseFromIstream(&stream)); 147 EXPECT_TRUE(stream.eof()); 148 TestUtil::ExpectAllFieldsSet(message); 149 } 150 151 { 152 // Test ParseFromBoundedZeroCopyStream. 153 string data_with_junk(data); 154 data_with_junk.append("some junk on the end"); 155 io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); 156 protobuf_unittest::TestAllTypes message; 157 EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size())); 158 TestUtil::ExpectAllFieldsSet(message); 159 } 160 161 { 162 // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if 163 // EOF is reached before the expected number of bytes. 164 io::ArrayInputStream stream(data.data(), data.size()); 165 protobuf_unittest::TestAllTypes message; 166 EXPECT_FALSE( 167 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); 168 } 169} 170 171TEST(MessageTest, ParseFailsIfNotInitialized) { 172 unittest::TestRequired message; 173 vector<string> errors; 174 175 { 176 ScopedMemoryLog log; 177 EXPECT_FALSE(message.ParseFromString("")); 178 errors = log.GetMessages(ERROR); 179 } 180 181 ASSERT_EQ(1, errors.size()); 182 EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" " 183 "because it is missing required fields: a, b, c", 184 errors[0]); 185} 186 187TEST(MessageTest, BypassInitializationCheckOnParse) { 188 unittest::TestRequired message; 189 io::ArrayInputStream raw_input(NULL, 0); 190 io::CodedInputStream input(&raw_input); 191 EXPECT_TRUE(message.MergePartialFromCodedStream(&input)); 192} 193 194TEST(MessageTest, InitializationErrorString) { 195 unittest::TestRequired message; 196 EXPECT_EQ("a, b, c", message.InitializationErrorString()); 197} 198 199#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet. 200 201TEST(MessageTest, SerializeFailsIfNotInitialized) { 202 unittest::TestRequired message; 203 string data; 204 EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)), 205 "Can't serialize message of type \"protobuf_unittest.TestRequired\" because " 206 "it is missing required fields: a, b, c"); 207} 208 209TEST(MessageTest, CheckInitialized) { 210 unittest::TestRequired message; 211 EXPECT_DEATH(message.CheckInitialized(), 212 "Message of type \"protobuf_unittest.TestRequired\" is missing required " 213 "fields: a, b, c"); 214} 215 216#endif // GTEST_HAS_DEATH_TEST 217 218TEST(MessageTest, BypassInitializationCheckOnSerialize) { 219 unittest::TestRequired message; 220 io::ArrayOutputStream raw_output(NULL, 0); 221 io::CodedOutputStream output(&raw_output); 222 EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); 223} 224 225TEST(MessageTest, FindInitializationErrors) { 226 unittest::TestRequired message; 227 vector<string> errors; 228 message.FindInitializationErrors(&errors); 229 ASSERT_EQ(3, errors.size()); 230 EXPECT_EQ("a", errors[0]); 231 EXPECT_EQ("b", errors[1]); 232 EXPECT_EQ("c", errors[2]); 233} 234 235TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { 236 unittest::TestAllTypes message; 237 238 // Control case. 239 EXPECT_TRUE(message.ParseFromArray("", 0)); 240 241 // The byte is a valid varint, but not a valid tag (zero). 242 EXPECT_FALSE(message.ParseFromArray("\0", 1)); 243 244 // The byte is a malformed varint. 245 EXPECT_FALSE(message.ParseFromArray("\200", 1)); 246 247 // The byte is an endgroup tag, but we aren't parsing a group. 248 EXPECT_FALSE(message.ParseFromArray("\014", 1)); 249} 250 251TEST(MessageFactoryTest, GeneratedFactoryLookup) { 252 EXPECT_EQ( 253 MessageFactory::generated_factory()->GetPrototype( 254 protobuf_unittest::TestAllTypes::descriptor()), 255 &protobuf_unittest::TestAllTypes::default_instance()); 256} 257 258TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { 259 // Construct a new descriptor. 260 DescriptorPool pool; 261 FileDescriptorProto file; 262 file.set_name("foo.proto"); 263 file.add_message_type()->set_name("Foo"); 264 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); 265 266 // Trying to construct it should return NULL. 267 EXPECT_TRUE( 268 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); 269} 270 271} // namespace protobuf 272} // namespace google 273