diff options
Diffstat (limited to 'src/google/protobuf/wire_format_unittest.cc')
-rw-r--r-- | src/google/protobuf/wire_format_unittest.cc | 247 |
1 files changed, 231 insertions, 16 deletions
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index 867970c..3a44aaf 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -44,7 +44,7 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/stubs/stl_util-inl.h> +#include <google/protobuf/stubs/stl_util.h> namespace google { namespace protobuf { @@ -175,6 +175,43 @@ TEST(WireFormatTest, ParsePackedExtensions) { TestUtil::ExpectPackedExtensionsSet(dest); } +TEST(WireFormatTest, ParseOneof) { + unittest::TestOneof2 source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetOneof1(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectOneofSet1(dest); +} + +TEST(WireFormatTest, OneofOnlySetLast) { + unittest::TestOneofBackwardsCompatible source; + unittest::TestOneof oneof_dest; + string data; + + // Set two fields + source.set_foo_int(100); + source.set_foo_string("101"); + + // Serialize and parse to oneof message. + source.SerializeToString(&data); + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &oneof_dest); + + // Only the last field is set. + EXPECT_FALSE(oneof_dest.has_foo_int()); + EXPECT_TRUE(oneof_dest.has_foo_string()); +} + TEST(WireFormatTest, ByteSize) { unittest::TestAllTypes message; TestUtil::SetAllFields(&message); @@ -217,6 +254,18 @@ TEST(WireFormatTest, ByteSizePackedExtensions) { EXPECT_EQ(0, WireFormat::ByteSize(message)); } +TEST(WireFormatTest, ByteSizeOneof) { + unittest::TestOneof2 message; + TestUtil::SetOneof1(&message); + + EXPECT_EQ(message.ByteSize(), + WireFormat::ByteSize(message)); + message.Clear(); + + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + TEST(WireFormatTest, Serialize) { unittest::TestAllTypes message; string generated_data; @@ -311,6 +360,36 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) { TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data); } +TEST(WireFormatTest, SerializeOneof) { + unittest::TestOneof2 message; + string generated_data; + string dynamic_data; + + TestUtil::SetOneof1(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); +} + TEST(WireFormatTest, ParseMultipleExtensionRanges) { // Make sure we can parse a message that contains multiple extensions ranges. unittest::TestFieldOrderings source; @@ -480,6 +559,54 @@ TEST(WireFormatTest, ParseMessageSet) { EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString()); } +TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { + string data; + { + unittest::TestMessageSetExtension1 message; + message.set_i(123); + // Build a MessageSet manually with its message content put before its + // type_id. + io::StringOutputStream output_stream(&data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag); + // Write the message content first. + WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + &coded_output); + coded_output.WriteVarint32(message.ByteSize()); + message.SerializeWithCachedSizes(&coded_output); + // Write the type id. + uint32 type_id = message.GetDescriptor()->extension(0)->number(); + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + type_id, &coded_output); + coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); + } + { + unittest::TestMessageSet message_set; + ASSERT_TRUE(message_set.ParseFromString(data)); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } + { + // Test parse the message via Reflection. + unittest::TestMessageSet message_set; + io::CodedInputStream input( + reinterpret_cast<const uint8*>(data.data()), data.size()); + EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set)); + EXPECT_TRUE(input.ConsumedEntireMessage()); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } +} + +TEST(WireFormatTest, ParseBrokenMessageSet) { + unittest::TestMessageSet message_set; + string input("goodbye"); // Invalid wire format data. + EXPECT_FALSE(message_set.ParseFromString(input)); +} + TEST(WireFormatTest, RecursionLimit) { unittest::TestRecursiveMessage message; message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1); @@ -639,6 +766,34 @@ TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) { EXPECT_EQ(msg1.DebugString(), msg2.DebugString()); } +TEST(WireFormatTest, CompatibleTypes) { + const int64 data = 0x100000000; + unittest::Int64Message msg1; + msg1.set_data(data); + string serialized; + msg1.SerializeToString(&serialized); + + // Test int64 is compatible with bool + unittest::BoolMessage msg2; + ASSERT_TRUE(msg2.ParseFromString(serialized)); + ASSERT_EQ(static_cast<bool>(data), msg2.data()); + + // Test int64 is compatible with uint64 + unittest::Uint64Message msg3; + ASSERT_TRUE(msg3.ParseFromString(serialized)); + ASSERT_EQ(static_cast<uint64>(data), msg3.data()); + + // Test int64 is compatible with int32 + unittest::Int32Message msg4; + ASSERT_TRUE(msg4.ParseFromString(serialized)); + ASSERT_EQ(static_cast<int32>(data), msg4.data()); + + // Test int64 is compatible with uint32 + unittest::Uint32Message msg5; + ASSERT_TRUE(msg5.ParseFromString(serialized)); + ASSERT_EQ(static_cast<uint32>(data), msg5.data()); +} + class WireFormatInvalidInputTest : public testing::Test { protected: // Make a serialized TestAllTypes in which the field optional_nested_message @@ -800,7 +955,20 @@ bool ReadMessage(const string &wire_buffer, T *message) { return message->ParseFromArray(wire_buffer.data(), wire_buffer.size()); } -TEST(Utf8ValidationTest, WriteInvalidUTF8String) { +bool StartsWith(const string& s, const string& prefix) { + return s.substr(0, prefix.length()) == prefix; +} + +class Utf8ValidationTest : public ::testing::Test { + protected: + Utf8ValidationTest() {} + virtual ~Utf8ValidationTest() {} + virtual void SetUp() { + } + +}; + +TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector<string> errors; @@ -811,17 +979,17 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) { } #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Encountered string containing invalid UTF-8 data while " - "serializing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes.", - errors[0]); - + EXPECT_TRUE(StartsWith(errors[0], + "String field 'data' contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); #else ASSERT_EQ(0, errors.size()); #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, ReadInvalidUTF8String) { + +TEST_F(Utf8ValidationTest, ReadInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -834,17 +1002,18 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) { } #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Encountered string containing invalid UTF-8 data while " - "parsing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes.", - errors[0]); + EXPECT_TRUE(StartsWith(errors[0], + "String field 'data' contains invalid UTF-8 data when " + "parsing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); #else ASSERT_EQ(0, errors.size()); #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, WriteValidUTF8String) { + +TEST_F(Utf8ValidationTest, WriteValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector<string> errors; @@ -856,7 +1025,7 @@ TEST(Utf8ValidationTest, WriteValidUTF8String) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadValidUTF8String) { +TEST_F(Utf8ValidationTest, ReadValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kValidUTF8String, &input, &wire_buffer); @@ -872,7 +1041,7 @@ TEST(Utf8ValidationTest, ReadValidUTF8String) { } // Bytes: anything can pass as bytes, use invalid UTF-8 string to test -TEST(Utf8ValidationTest, WriteArbitraryBytes) { +TEST_F(Utf8ValidationTest, WriteArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; vector<string> errors; @@ -884,7 +1053,7 @@ TEST(Utf8ValidationTest, WriteArbitraryBytes) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadArbitraryBytes) { +TEST_F(Utf8ValidationTest, ReadArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -899,6 +1068,52 @@ TEST(Utf8ValidationTest, ReadArbitraryBytes) { EXPECT_EQ(input.data(), output.data()); } +TEST_F(Utf8ValidationTest, ParseRepeatedString) { + protobuf_unittest::MoreBytes input; + input.add_data(kValidUTF8String); + input.add_data(kInvalidUTF8String); + input.add_data(kInvalidUTF8String); + string wire_buffer = input.SerializeAsString(); + + protobuf_unittest::MoreString output; + vector<string> errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(2, errors.size()); +#else + ASSERT_EQ(0, errors.size()); +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + EXPECT_EQ(wire_buffer, output.SerializeAsString()); +} + +// Test the old VerifyUTF8String() function, which may still be called by old +// generated code. +TEST_F(Utf8ValidationTest, OldVerifyUTF8String) { + string data(kInvalidUTF8String); + + vector<string> errors; + { + ScopedMemoryLog log; + WireFormat::VerifyUTF8String(data.data(), data.size(), + WireFormat::SERIALIZE); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(1, errors.size()); + EXPECT_TRUE(StartsWith(errors[0], + "String field contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); +#else + ASSERT_EQ(0, errors.size()); +#endif +} + + } // namespace } // namespace internal } // namespace protobuf |