1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 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// This file needs to be included as .inc as it depends on certain macros being 36// defined prior to its inclusion. 37 38#include <google/protobuf/message.h> 39 40#include <fcntl.h> 41#include <sys/stat.h> 42#include <sys/types.h> 43#ifndef _MSC_VER 44#include <unistd.h> 45#endif 46#include <fstream> 47#include <sstream> 48 49#include <google/protobuf/stubs/logging.h> 50#include <google/protobuf/stubs/common.h> 51#include <google/protobuf/stubs/logging.h> 52#include <google/protobuf/test_util2.h> 53#include <google/protobuf/io/io_win32.h> 54#include <google/protobuf/io/coded_stream.h> 55#include <google/protobuf/io/zero_copy_stream.h> 56#include <google/protobuf/io/zero_copy_stream_impl.h> 57#include <google/protobuf/descriptor.pb.h> 58#include <google/protobuf/arena.h> 59#include <google/protobuf/descriptor.h> 60#include <google/protobuf/generated_message_reflection.h> 61#include <google/protobuf/testing/googletest.h> 62#include <gtest/gtest.h> 63 64 65namespace google { 66namespace protobuf { 67 68#if defined(_WIN32) 69// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import 70// them like we do below. 71using google::protobuf::io::win32::close; 72using google::protobuf::io::win32::open; 73#endif 74 75#ifndef O_BINARY 76#ifdef _O_BINARY 77#define O_BINARY _O_BINARY 78#else 79#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. 80#endif 81#endif 82 83TEST(MESSAGE_TEST_NAME, SerializeHelpers) { 84 // TODO(kenton): Test more helpers? They're all two-liners so it seems 85 // like a waste of time. 86 87 UNITTEST::TestAllTypes message; 88 TestUtil::SetAllFields(&message); 89 std::stringstream stream; 90 91 std::string str1("foo"); 92 std::string str2("bar"); 93 94 EXPECT_TRUE(message.SerializeToString(&str1)); 95 EXPECT_TRUE(message.AppendToString(&str2)); 96 EXPECT_TRUE(message.SerializeToOstream(&stream)); 97 98 EXPECT_EQ(str1.size() + 3, str2.size()); 99 EXPECT_EQ("bar", str2.substr(0, 3)); 100 // Don't use EXPECT_EQ because we don't want to dump raw binary data to 101 // stdout. 102 EXPECT_TRUE(str2.substr(3) == str1); 103 104 // GCC gives some sort of error if we try to just do stream.str() == str1. 105 std::string temp = stream.str(); 106 EXPECT_TRUE(temp == str1); 107 108 EXPECT_TRUE(message.SerializeAsString() == str1); 109 110} 111 112TEST(MESSAGE_TEST_NAME, SerializeToBrokenOstream) { 113 std::ofstream out; 114 UNITTEST::TestAllTypes message; 115 message.set_optional_int32(123); 116 117 EXPECT_FALSE(message.SerializeToOstream(&out)); 118} 119 120TEST(MESSAGE_TEST_NAME, ParseFromFileDescriptor) { 121 std::string filename = 122 TestUtil::GetTestDataPath("net/proto2/internal/testdata/golden_message"); 123 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 124 ASSERT_GE(file, 0); 125 126 UNITTEST::TestAllTypes message; 127 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 128 TestUtil::ExpectAllFieldsSet(message); 129 130 EXPECT_GE(close(file), 0); 131} 132 133TEST(MESSAGE_TEST_NAME, ParsePackedFromFileDescriptor) { 134 std::string filename = TestUtil::GetTestDataPath( 135 "net/proto2/internal/testdata/golden_packed_fields_message"); 136 int file = open(filename.c_str(), O_RDONLY | O_BINARY); 137 ASSERT_GE(file, 0); 138 139 UNITTEST::TestPackedTypes message; 140 EXPECT_TRUE(message.ParseFromFileDescriptor(file)); 141 TestUtil::ExpectPackedFieldsSet(message); 142 143 EXPECT_GE(close(file), 0); 144} 145 146TEST(MESSAGE_TEST_NAME, ParseHelpers) { 147 // TODO(kenton): Test more helpers? They're all two-liners so it seems 148 // like a waste of time. 149 std::string data; 150 151 { 152 // Set up. 153 UNITTEST::TestAllTypes message; 154 TestUtil::SetAllFields(&message); 155 message.SerializeToString(&data); 156 } 157 158 { 159 // Test ParseFromString. 160 UNITTEST::TestAllTypes message; 161 EXPECT_TRUE(message.ParseFromString(data)); 162 TestUtil::ExpectAllFieldsSet(message); 163 } 164 165 { 166 // Test ParseFromIstream. 167 UNITTEST::TestAllTypes message; 168 std::stringstream stream(data); 169 EXPECT_TRUE(message.ParseFromIstream(&stream)); 170 EXPECT_TRUE(stream.eof()); 171 TestUtil::ExpectAllFieldsSet(message); 172 } 173 174 { 175 // Test ParseFromBoundedZeroCopyStream. 176 std::string data_with_junk(data); 177 data_with_junk.append("some junk on the end"); 178 io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); 179 UNITTEST::TestAllTypes message; 180 EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size())); 181 TestUtil::ExpectAllFieldsSet(message); 182 } 183 184 { 185 // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if 186 // EOF is reached before the expected number of bytes. 187 io::ArrayInputStream stream(data.data(), data.size()); 188 UNITTEST::TestAllTypes message; 189 EXPECT_FALSE( 190 message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); 191 } 192} 193 194TEST(MESSAGE_TEST_NAME, ParseFailsIfNotInitialized) { 195 UNITTEST::TestRequired message; 196 std::vector<std::string> errors; 197 198 { 199 ScopedMemoryLog log; 200 EXPECT_FALSE(message.ParseFromString("")); 201 errors = log.GetMessages(ERROR); 202 } 203 204 ASSERT_EQ(1, errors.size()); 205 EXPECT_EQ( 206 "Can't parse message of type \"" + std::string(UNITTEST_PACKAGE_NAME) + 207 ".TestRequired\" because it is missing required fields: a, b, c", 208 errors[0]); 209} 210 211TEST(MESSAGE_TEST_NAME, BypassInitializationCheckOnParse) { 212 UNITTEST::TestRequired message; 213 io::ArrayInputStream raw_input(nullptr, 0); 214 io::CodedInputStream input(&raw_input); 215 EXPECT_TRUE(message.MergePartialFromCodedStream(&input)); 216} 217 218TEST(MESSAGE_TEST_NAME, InitializationErrorString) { 219 UNITTEST::TestRequired message; 220 EXPECT_EQ("a, b, c", message.InitializationErrorString()); 221} 222 223TEST(MESSAGE_TEST_NAME, DynamicCastToGenerated) { 224 UNITTEST::TestAllTypes test_all_types; 225 226 Message* test_all_types_pointer = &test_all_types; 227 EXPECT_EQ(&test_all_types, DynamicCastToGenerated<UNITTEST::TestAllTypes>( 228 test_all_types_pointer)); 229 EXPECT_EQ(nullptr, DynamicCastToGenerated<UNITTEST::TestRequired>( 230 test_all_types_pointer)); 231 232 const Message* test_all_types_pointer_const = &test_all_types; 233 EXPECT_EQ(&test_all_types, 234 DynamicCastToGenerated<const UNITTEST::TestAllTypes>( 235 test_all_types_pointer_const)); 236 EXPECT_EQ(nullptr, DynamicCastToGenerated<const UNITTEST::TestRequired>( 237 test_all_types_pointer_const)); 238} 239 240#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. 241 242TEST(MESSAGE_TEST_NAME, SerializeFailsIfNotInitialized) { 243 UNITTEST::TestRequired message; 244 std::string data; 245 EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)), 246 "Can't serialize message of type \"" + 247 std::string(UNITTEST_PACKAGE_NAME) + 248 ".TestRequired\" because " 249 "it is missing required fields: a, b, c"); 250} 251 252TEST(MESSAGE_TEST_NAME, CheckInitialized) { 253 UNITTEST::TestRequired message; 254 EXPECT_DEATH(message.CheckInitialized(), 255 "Message of type \"" + std::string(UNITTEST_PACKAGE_NAME) + 256 ".TestRequired\" is missing required " 257 "fields: a, b, c"); 258} 259 260#endif // PROTOBUF_HAS_DEATH_TEST 261 262namespace { 263// An input stream that repeats a std::string's content for a number of times. 264// It helps us create a really large input without consuming too much memory. 265// Used to test the parsing behavior when the input size exceeds 2G or close to 266// it. 267class RepeatedInputStream : public io::ZeroCopyInputStream { 268 public: 269 RepeatedInputStream(const std::string& data, size_t count) 270 : data_(data), count_(count), position_(0), total_byte_count_(0) {} 271 272 virtual bool Next(const void** data, int* size) { 273 if (position_ == data_.size()) { 274 if (--count_ == 0) { 275 return false; 276 } 277 position_ = 0; 278 } 279 *data = &data_[position_]; 280 *size = static_cast<int>(data_.size() - position_); 281 position_ = data_.size(); 282 total_byte_count_ += *size; 283 return true; 284 } 285 286 virtual void BackUp(int count) { 287 position_ -= static_cast<size_t>(count); 288 total_byte_count_ -= count; 289 } 290 291 virtual bool Skip(int count) { 292 while (count > 0) { 293 const void* data; 294 int size; 295 if (!Next(&data, &size)) { 296 break; 297 } 298 if (size >= count) { 299 BackUp(size - count); 300 return true; 301 } else { 302 count -= size; 303 } 304 } 305 return false; 306 } 307 308 virtual int64 ByteCount() const { return total_byte_count_; } 309 310 private: 311 std::string data_; 312 size_t count_; // The number of strings that haven't been consuemd. 313 size_t position_; // Position in the std::string for the next read. 314 int64 total_byte_count_; 315}; 316} // namespace 317 318TEST(MESSAGE_TEST_NAME, TestParseMessagesCloseTo2G) { 319 // Create a message with a large std::string field. 320 std::string value = std::string(64 * 1024 * 1024, 'x'); 321 UNITTEST::TestAllTypes message; 322 message.set_optional_string(value); 323 324 // Repeat this message in the input stream to make the total input size 325 // close to 2G. 326 std::string data = message.SerializeAsString(); 327 size_t count = static_cast<size_t>(kint32max) / data.size(); 328 RepeatedInputStream input(data, count); 329 330 // The parsing should succeed. 331 UNITTEST::TestAllTypes result; 332 EXPECT_TRUE(result.ParseFromZeroCopyStream(&input)); 333 334 // When there are multiple occurences of a singulr field, the last one 335 // should win. 336 EXPECT_EQ(value, result.optional_string()); 337} 338 339TEST(MESSAGE_TEST_NAME, TestParseMessagesOver2G) { 340 // Create a message with a large std::string field. 341 std::string value = std::string(64 * 1024 * 1024, 'x'); 342 UNITTEST::TestAllTypes message; 343 message.set_optional_string(value); 344 345 // Repeat this message in the input stream to make the total input size 346 // larger than 2G. 347 std::string data = message.SerializeAsString(); 348 size_t count = static_cast<size_t>(kint32max) / data.size() + 1; 349 RepeatedInputStream input(data, count); 350 351 // The parsing should fail. 352 UNITTEST::TestAllTypes result; 353 EXPECT_FALSE(result.ParseFromZeroCopyStream(&input)); 354} 355 356TEST(MESSAGE_TEST_NAME, BypassInitializationCheckOnSerialize) { 357 UNITTEST::TestRequired message; 358 io::ArrayOutputStream raw_output(nullptr, 0); 359 io::CodedOutputStream output(&raw_output); 360 EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); 361} 362 363TEST(MESSAGE_TEST_NAME, FindInitializationErrors) { 364 UNITTEST::TestRequired message; 365 std::vector<std::string> errors; 366 message.FindInitializationErrors(&errors); 367 ASSERT_EQ(3, errors.size()); 368 EXPECT_EQ("a", errors[0]); 369 EXPECT_EQ("b", errors[1]); 370 EXPECT_EQ("c", errors[2]); 371} 372 373TEST(MESSAGE_TEST_NAME, ParseFailsOnInvalidMessageEnd) { 374 UNITTEST::TestAllTypes message; 375 376 // Control case. 377 EXPECT_TRUE(message.ParseFromArray("", 0)); 378 379 // The byte is a valid varint, but not a valid tag (zero). 380 EXPECT_FALSE(message.ParseFromArray("\0", 1)); 381 382 // The byte is a malformed varint. 383 EXPECT_FALSE(message.ParseFromArray("\200", 1)); 384 385 // The byte is an endgroup tag, but we aren't parsing a group. 386 EXPECT_FALSE(message.ParseFromArray("\014", 1)); 387} 388 389// Regression test for b/23630858 390TEST(MESSAGE_TEST_NAME, MessageIsStillValidAfterParseFails) { 391 UNITTEST::TestAllTypes message; 392 393 // 9 0xFFs for the "optional_uint64" field. 394 std::string invalid_data = "\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; 395 396 EXPECT_FALSE(message.ParseFromString(invalid_data)); 397 message.Clear(); 398 EXPECT_EQ(0, message.optional_uint64()); 399 400 // invalid data for field "optional_string". Length prefix is 1 but no 401 // payload. 402 std::string invalid_string_data = "\x72\x01"; 403 { 404 Arena arena; 405 UNITTEST::TestAllTypes* arena_message = 406 Arena::CreateMessage<UNITTEST::TestAllTypes>(&arena); 407 EXPECT_FALSE(arena_message->ParseFromString(invalid_string_data)); 408 arena_message->Clear(); 409 EXPECT_EQ("", arena_message->optional_string()); 410 } 411} 412 413 414namespace { 415 416void ExpectMessageMerged(const UNITTEST::TestAllTypes& message) { 417 EXPECT_EQ(3, message.optional_int32()); 418 EXPECT_EQ(2, message.optional_int64()); 419 EXPECT_EQ("hello", message.optional_string()); 420} 421 422void AssignParsingMergeMessages(UNITTEST::TestAllTypes* msg1, 423 UNITTEST::TestAllTypes* msg2, 424 UNITTEST::TestAllTypes* msg3) { 425 msg1->set_optional_int32(1); 426 msg2->set_optional_int64(2); 427 msg3->set_optional_int32(3); 428 msg3->set_optional_string("hello"); 429} 430 431} // namespace 432 433// Test that if an optional or required message/group field appears multiple 434// times in the input, they need to be merged. 435TEST(MESSAGE_TEST_NAME, ParsingMerge) { 436 UNITTEST::TestParsingMerge::RepeatedFieldsGenerator generator; 437 UNITTEST::TestAllTypes* msg1; 438 UNITTEST::TestAllTypes* msg2; 439 UNITTEST::TestAllTypes* msg3; 440 441#define ASSIGN_REPEATED_FIELD(FIELD) \ 442 msg1 = generator.add_##FIELD(); \ 443 msg2 = generator.add_##FIELD(); \ 444 msg3 = generator.add_##FIELD(); \ 445 AssignParsingMergeMessages(msg1, msg2, msg3) 446 447 ASSIGN_REPEATED_FIELD(field1); 448 ASSIGN_REPEATED_FIELD(field2); 449 ASSIGN_REPEATED_FIELD(field3); 450 ASSIGN_REPEATED_FIELD(ext1); 451 ASSIGN_REPEATED_FIELD(ext2); 452 453#undef ASSIGN_REPEATED_FIELD 454#define ASSIGN_REPEATED_GROUP(FIELD) \ 455 msg1 = generator.add_##FIELD()->mutable_field1(); \ 456 msg2 = generator.add_##FIELD()->mutable_field1(); \ 457 msg3 = generator.add_##FIELD()->mutable_field1(); \ 458 AssignParsingMergeMessages(msg1, msg2, msg3) 459 460 ASSIGN_REPEATED_GROUP(group1); 461 ASSIGN_REPEATED_GROUP(group2); 462 463#undef ASSIGN_REPEATED_GROUP 464 465 std::string buffer; 466 generator.SerializeToString(&buffer); 467 UNITTEST::TestParsingMerge parsing_merge; 468 parsing_merge.ParseFromString(buffer); 469 470 // Required and optional fields should be merged. 471 ExpectMessageMerged(parsing_merge.required_all_types()); 472 ExpectMessageMerged(parsing_merge.optional_all_types()); 473 ExpectMessageMerged(parsing_merge.optionalgroup().optional_group_all_types()); 474 ExpectMessageMerged( 475 parsing_merge.GetExtension(UNITTEST::TestParsingMerge::optional_ext)); 476 477 // Repeated fields should not be merged. 478 EXPECT_EQ(3, parsing_merge.repeated_all_types_size()); 479 EXPECT_EQ(3, parsing_merge.repeatedgroup_size()); 480 EXPECT_EQ( 481 3, parsing_merge.ExtensionSize(UNITTEST::TestParsingMerge::repeated_ext)); 482} 483 484TEST(MESSAGE_TEST_NAME, MergeFrom) { 485 UNITTEST::TestAllTypes source, dest; 486 487 // Optional fields 488 source.set_optional_int32(1); // only source 489 source.set_optional_int64(2); // both source and dest 490 dest.set_optional_int64(3); 491 dest.set_optional_uint32(4); // only dest 492 493 // Optional fields with defaults 494 source.set_default_int32(13); // only source 495 source.set_default_int64(14); // both source and dest 496 dest.set_default_int64(15); 497 dest.set_default_uint32(16); // only dest 498 499 // Repeated fields 500 source.add_repeated_int32(5); // only source 501 source.add_repeated_int32(6); 502 source.add_repeated_int64(7); // both source and dest 503 source.add_repeated_int64(8); 504 dest.add_repeated_int64(9); 505 dest.add_repeated_int64(10); 506 dest.add_repeated_uint32(11); // only dest 507 dest.add_repeated_uint32(12); 508 509 dest.MergeFrom(source); 510 511 // Optional fields: source overwrites dest if source is specified 512 EXPECT_EQ(1, dest.optional_int32()); // only source: use source 513 EXPECT_EQ(2, dest.optional_int64()); // source and dest: use source 514 EXPECT_EQ(4, dest.optional_uint32()); // only dest: use dest 515 EXPECT_EQ(0, dest.optional_uint64()); // neither: use default 516 517 // Optional fields with defaults 518 EXPECT_EQ(13, dest.default_int32()); // only source: use source 519 EXPECT_EQ(14, dest.default_int64()); // source and dest: use source 520 EXPECT_EQ(16, dest.default_uint32()); // only dest: use dest 521 EXPECT_EQ(44, dest.default_uint64()); // neither: use default 522 523 // Repeated fields: concatenate source onto the end of dest 524 ASSERT_EQ(2, dest.repeated_int32_size()); 525 EXPECT_EQ(5, dest.repeated_int32(0)); 526 EXPECT_EQ(6, dest.repeated_int32(1)); 527 ASSERT_EQ(4, dest.repeated_int64_size()); 528 EXPECT_EQ(9, dest.repeated_int64(0)); 529 EXPECT_EQ(10, dest.repeated_int64(1)); 530 EXPECT_EQ(7, dest.repeated_int64(2)); 531 EXPECT_EQ(8, dest.repeated_int64(3)); 532 ASSERT_EQ(2, dest.repeated_uint32_size()); 533 EXPECT_EQ(11, dest.repeated_uint32(0)); 534 EXPECT_EQ(12, dest.repeated_uint32(1)); 535 ASSERT_EQ(0, dest.repeated_uint64_size()); 536} 537 538TEST(MESSAGE_TEST_NAME, IsInitialized) { 539 UNITTEST::TestIsInitialized msg; 540 EXPECT_TRUE(msg.IsInitialized()); 541 UNITTEST::TestIsInitialized::SubMessage* sub_message = 542 msg.mutable_sub_message(); 543 EXPECT_TRUE(msg.IsInitialized()); 544 UNITTEST::TestIsInitialized::SubMessage::SubGroup* sub_group = 545 sub_message->mutable_subgroup(); 546 EXPECT_FALSE(msg.IsInitialized()); 547 sub_group->set_i(1); 548 EXPECT_TRUE(msg.IsInitialized()); 549} 550 551TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryLookup) { 552 EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype( 553 UNITTEST::TestAllTypes::descriptor()), 554 &UNITTEST::TestAllTypes::default_instance()); 555} 556 557TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryUnknownType) { 558 // Construct a new descriptor. 559 DescriptorPool pool; 560 FileDescriptorProto file; 561 file.set_name("foo.proto"); 562 file.add_message_type()->set_name("Foo"); 563 const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); 564 565 // Trying to construct it should return nullptr. 566 EXPECT_TRUE(MessageFactory::generated_factory()->GetPrototype(descriptor) == 567 nullptr); 568} 569 570TEST(MESSAGE_TEST_NAME, MOMIParserEdgeCases) { 571 { 572 UNITTEST::TestAllTypes msg; 573 // Parser ends in last 16 bytes of buffer due to a 0. 574 std::string data; 575 // 12 bytes of data 576 for (int i = 0; i < 4; i++) data += "\370\1\1"; 577 // 13 byte is terminator 578 data += '\0'; // Terminator 579 // followed by the rest of the stream 580 // space is ascii 32 so no end group 581 data += std::string(30, ' '); 582 io::ArrayInputStream zcis(data.data(), data.size(), 17); 583 io::CodedInputStream cis(&zcis); 584 EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); 585 EXPECT_EQ(cis.CurrentPosition(), 3 * 4 + 1); 586 } 587 { 588 // Parser ends in last 16 bytes of buffer due to a end-group. 589 // Must use a message that is a group. Otherwise ending on a group end is 590 // a failure. 591 UNITTEST::TestAllTypes::OptionalGroup msg; 592 std::string data; 593 for (int i = 0; i < 3; i++) data += "\370\1\1"; 594 data += '\14'; // Octal end-group tag 12 (1 * 8 + 4( 595 data += std::string(30, ' '); 596 io::ArrayInputStream zcis(data.data(), data.size(), 17); 597 io::CodedInputStream cis(&zcis); 598 EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); 599 EXPECT_EQ(cis.CurrentPosition(), 3 * 3 + 1); 600 EXPECT_TRUE(cis.LastTagWas(12)); 601 } 602 { 603 // Parser ends in last 16 bytes of buffer due to a end-group. But is inside 604 // a length delimited field. 605 // a failure. 606 UNITTEST::TestAllTypes::OptionalGroup msg; 607 std::string data; 608 data += "\22\3foo"; 609 data += '\14'; // Octal end-group tag 12 (1 * 8 + 4( 610 data += std::string(30, ' '); 611 io::ArrayInputStream zcis(data.data(), data.size(), 17); 612 io::CodedInputStream cis(&zcis); 613 EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); 614 EXPECT_EQ(cis.CurrentPosition(), 6); 615 EXPECT_TRUE(cis.LastTagWas(12)); 616 } 617 { 618 // Parser fails when ending on 0 if from ZeroCopyInputStream 619 UNITTEST::TestAllTypes msg; 620 std::string data; 621 // 12 bytes of data 622 for (int i = 0; i < 4; i++) data += "\370\1\1"; 623 // 13 byte is terminator 624 data += '\0'; // Terminator 625 data += std::string(30, ' '); 626 io::ArrayInputStream zcis(data.data(), data.size(), 17); 627 EXPECT_FALSE(msg.ParsePartialFromZeroCopyStream(&zcis)); 628 } 629} 630 631 632} // namespace protobuf 633} // namespace google 634