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 GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet. 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 // GTEST_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 260TEST(MessageFactoryTest, GeneratedFactoryLookup) { 261 EXPECT_EQ( 262 MessageFactory::generated_factory()->GetPrototype( 263 protobuf_unittest::TestAllTypes::descriptor()), 264 &protobuf_unittest::TestAllTypes::default_instance()); 265} 266 267TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { 268 // Construct a new descriptor. 269 DescriptorPool pool; 270 FileDescriptorProto file; 271 file.set_name("foo.proto"); 272 file.add_message_type()->set_name("Foo"); 273 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); 274 275 // Trying to construct it should return NULL. 276 EXPECT_TRUE( 277 MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); 278} 279 280} // namespace protobuf 281} // namespace google 282