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 (at) 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 59 namespace google { 60 namespace 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 70 TEST(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 99 TEST(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 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); 111 112 unittest::TestAllTypes message; 113 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 114 TestUtil::ExpectAllFieldsSet(message); 115 116 EXPECT_GE(close(file), 0); 117 } 118 119 TEST(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 132 TEST(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 180 TEST(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 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)); 201 } 202 203 TEST(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 210 TEST(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 218 TEST(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 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)); 232 } 233 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]); 242 } 243 244 TEST(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 260 TEST(MessageFactoryTest, GeneratedFactoryLookup) { 261 EXPECT_EQ( 262 MessageFactory::generated_factory()->GetPrototype( 263 protobuf_unittest::TestAllTypes::descriptor()), 264 &protobuf_unittest::TestAllTypes::default_instance()); 265 } 266 267 TEST(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