diff options
Diffstat (limited to 'conformance/conformance_test.cc')
-rw-r--r-- | conformance/conformance_test.cc | 462 |
1 files changed, 343 insertions, 119 deletions
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index e9f3a8a8..f1b92056 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -34,11 +34,14 @@ #include "conformance.pb.h" #include "conformance_test.h" +#include <google/protobuf/test_messages_proto3.pb.h> +#include <google/protobuf/test_messages_proto2.pb.h> + #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/text_format.h> -#include <google/protobuf/util/json_util.h> #include <google/protobuf/util/field_comparator.h> +#include <google/protobuf/util/json_util.h> #include <google/protobuf/util/message_differencer.h> #include <google/protobuf/util/type_resolver_util.h> #include <google/protobuf/wire_format_lite.h> @@ -47,7 +50,6 @@ using conformance::ConformanceRequest; using conformance::ConformanceResponse; -using conformance::TestAllTypes; using conformance::WireFormat; using google::protobuf::Descriptor; using google::protobuf::FieldDescriptor; @@ -58,6 +60,8 @@ using google::protobuf::util::JsonToBinaryString; using google::protobuf::util::MessageDifferencer; using google::protobuf::util::NewTypeResolverForDescriptorPool; using google::protobuf::util::Status; +using protobuf_test_messages::proto3::TestAllTypesProto3; +using protobuf_test_messages::proto2::TestAllTypesProto2; using std::string; namespace { @@ -107,13 +111,18 @@ string cat(const string& a, const string& b, // The maximum number of bytes that it takes to encode a 64-bit varint. #define VARINT_MAX_LEN 10 -size_t vencode64(uint64_t val, char *buf) { +size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) { if (val == 0) { buf[0] = 0; return 1; } size_t i = 0; while (val) { uint8_t byte = val & 0x7fU; val >>= 7; - if (val) byte |= 0x80U; + if (val || over_encoded_bytes) byte |= 0x80U; + buf[i++] = byte; + } + while (over_encoded_bytes--) { + assert(i < 10); + uint8_t byte = over_encoded_bytes ? 0x80 : 0; buf[i++] = byte; } return i; @@ -121,7 +130,15 @@ size_t vencode64(uint64_t val, char *buf) { string varint(uint64_t x) { char buf[VARINT_MAX_LEN]; - size_t len = vencode64(x, buf); + size_t len = vencode64(x, 0, buf); + return string(buf, len); +} + +// Encodes a varint that is |extra| bytes longer than it needs to be, but still +// valid. +string longvarint(uint64_t x, int extra) { + char buf[VARINT_MAX_LEN]; + size_t len = vencode64(x, extra, buf); return string(buf, len); } @@ -130,8 +147,8 @@ string fixed32(void *data) { return string(static_cast<char*>(data), 4); } string fixed64(void *data) { return string(static_cast<char*>(data), 8); } string delim(const string& buf) { return cat(varint(buf.size()), buf); } -string uint32(uint32_t u32) { return fixed32(&u32); } -string uint64(uint64_t u64) { return fixed64(&u64); } +string u32(uint32_t u32) { return fixed32(&u32); } +string u64(uint64_t u64) { return fixed64(&u64); } string flt(float f) { return fixed32(&f); } string dbl(double d) { return fixed64(&d); } string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); } @@ -147,16 +164,19 @@ string submsg(uint32_t fn, const string& buf) { #define UNKNOWN_FIELD 666 -uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) { - const Descriptor* d = TestAllTypes().GetDescriptor(); +const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, + bool repeated, bool isProto3) { + + const Descriptor* d = isProto3 ? + TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor(); for (int i = 0; i < d->field_count(); i++) { const FieldDescriptor* f = d->field(i); if (f->type() == type && f->is_repeated() == repeated) { - return f->number(); + return f; } } GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type; - return 0; + return nullptr; } string UpperCase(string str) { @@ -255,10 +275,19 @@ void ConformanceTestSuite::RunTest(const string& test_name, void ConformanceTestSuite::RunValidInputTest( const string& test_name, ConformanceLevel level, const string& input, WireFormat input_format, const string& equivalent_text_format, - WireFormat requested_output) { - TestAllTypes reference_message; + WireFormat requested_output, bool isProto3) { + auto newTestMessage = [&isProto3]() { + Message* newMessage; + if (isProto3) { + newMessage = new TestAllTypesProto3; + } else { + newMessage = new TestAllTypesProto2; + } + return newMessage; + }; + Message* reference_message = newTestMessage(); GOOGLE_CHECK( - TextFormat::ParseFromString(equivalent_text_format, &reference_message)) + TextFormat::ParseFromString(equivalent_text_format, reference_message)) << "Failed to parse data for test case: " << test_name << ", data: " << equivalent_text_format; @@ -266,13 +295,21 @@ void ConformanceTestSuite::RunValidInputTest( ConformanceResponse response; switch (input_format) { - case conformance::PROTOBUF: + case conformance::PROTOBUF: { request.set_protobuf_payload(input); + if (isProto3) { + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); + } else { + request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); + } break; + } - case conformance::JSON: + case conformance::JSON: { + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); request.set_json_payload(input); break; + } default: GOOGLE_LOG(FATAL) << "Unspecified input format"; @@ -282,7 +319,7 @@ void ConformanceTestSuite::RunValidInputTest( RunTest(test_name, request, &response); - TestAllTypes test_message; + Message *test_message = newTestMessage(); switch (response.result_case()) { case ConformanceResponse::RESULT_NOT_SET: @@ -318,10 +355,10 @@ void ConformanceTestSuite::RunValidInputTest( return; } - if (!test_message.ParseFromString(binary_protobuf)) { + if (!test_message->ParseFromString(binary_protobuf)) { ReportFailure(test_name, level, request, response, - "INTERNAL ERROR: internal JSON->protobuf transcode " - "yielded unparseable proto."); + "INTERNAL ERROR: internal JSON->protobuf transcode " + "yielded unparseable proto."); return; } @@ -336,9 +373,9 @@ void ConformanceTestSuite::RunValidInputTest( return; } - if (!test_message.ParseFromString(response.protobuf_payload())) { + if (!test_message->ParseFromString(response.protobuf_payload())) { ReportFailure(test_name, level, request, response, - "Protobuf output we received from test was unparseable."); + "Protobuf output we received from test was unparseable."); return; } @@ -357,7 +394,9 @@ void ConformanceTestSuite::RunValidInputTest( string differences; differencer.ReportDifferencesToString(&differences); - if (differencer.Compare(reference_message, test_message)) { + bool check; + check = differencer.Compare(*reference_message, *test_message); + if (check) { ReportSuccess(test_name); } else { ReportFailure(test_name, level, request, response, @@ -365,14 +404,19 @@ void ConformanceTestSuite::RunValidInputTest( differences.c_str()); } } - -// Expect that this precise protobuf will cause a parse error. -void ConformanceTestSuite::ExpectParseFailureForProto( - const string& proto, const string& test_name, ConformanceLevel level) { +void ConformanceTestSuite::ExpectParseFailureForProtoWithProtoVersion ( + const string& proto, const string& test_name, ConformanceLevel level, + bool isProto3) { ConformanceRequest request; ConformanceResponse response; request.set_protobuf_payload(proto); + if (isProto3) { + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); + } else { + request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); + } string effective_test_name = ConformanceLevelToString(level) + + (isProto3 ? ".Proto3" : ".Proto2") + ".ProtobufInput." + test_name; // We don't expect output, but if the program erroneously accepts the protobuf @@ -390,6 +434,13 @@ void ConformanceTestSuite::ExpectParseFailureForProto( } } +// Expect that this precise protobuf will cause a parse error. +void ConformanceTestSuite::ExpectParseFailureForProto( + const string& proto, const string& test_name, ConformanceLevel level) { + ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true); + ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false); +} + // Expect that this protobuf will cause a parse error, even if it is followed // by valid protobuf data. We can try running this twice: once with this // data verbatim and once with this data followed by some valid data. @@ -404,33 +455,48 @@ void ConformanceTestSuite::RunValidJsonTest( const string& test_name, ConformanceLevel level, const string& input_json, const string& equivalent_text_format) { RunValidInputTest( - ConformanceLevelToString(level) + ".JsonInput." + test_name + + ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + ".ProtobufOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::PROTOBUF); + equivalent_text_format, conformance::PROTOBUF, true); RunValidInputTest( - ConformanceLevelToString(level) + ".JsonInput." + test_name + + ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + ".JsonOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::JSON); + equivalent_text_format, conformance::JSON, true); } void ConformanceTestSuite::RunValidJsonTestWithProtobufInput( - const string& test_name, ConformanceLevel level, const TestAllTypes& input, + const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input, const string& equivalent_text_format) { RunValidInputTest( - ConformanceLevelToString(level) + ".ProtobufInput." + test_name + + ConformanceLevelToString(level) + ".Proto3" + ".ProtobufInput." + test_name + ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF, - equivalent_text_format, conformance::JSON); + equivalent_text_format, conformance::JSON, true); } void ConformanceTestSuite::RunValidProtobufTest( - const string& test_name, ConformanceLevel level, const TestAllTypes& input, - const string& equivalent_text_format) { - RunValidInputTest("ProtobufInput." + test_name + ".ProtobufOutput", level, - input.SerializeAsString(), conformance::PROTOBUF, - equivalent_text_format, conformance::PROTOBUF); - RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput", level, - input.SerializeAsString(), conformance::PROTOBUF, - equivalent_text_format, conformance::JSON); + const string& test_name, ConformanceLevel level, + const string& input_protobuf, const string& equivalent_text_format, + bool isProto3) { + string rname = ".Proto3"; + if (!isProto3) { + rname = ".Proto2"; + } + RunValidInputTest( + ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + + ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF, + equivalent_text_format, conformance::PROTOBUF, isProto3); + if (isProto3) { + RunValidInputTest( + ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + + ".JsonOutput", level, input_protobuf, conformance::PROTOBUF, + equivalent_text_format, conformance::JSON, isProto3); + } +} + +void ConformanceTestSuite::RunValidProtobufTestWithMessage( + const string& test_name, ConformanceLevel level, const Message *input, + const string& equivalent_text_format, bool isProto3) { + RunValidProtobufTest(test_name, level, input->SerializeAsString(), equivalent_text_format, isProto3); } // According to proto3 JSON specification, JSON serializers follow more strict @@ -445,9 +511,10 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator( ConformanceResponse response; request.set_json_payload(input_json); request.set_requested_output_format(conformance::JSON); + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); string effective_test_name = ConformanceLevelToString(level) + - ".JsonInput." + test_name + ".Validator"; + ".Proto3.JsonInput." + test_name + ".Validator"; RunTest(effective_test_name, request, &response); @@ -483,8 +550,9 @@ void ConformanceTestSuite::ExpectParseFailureForJson( ConformanceRequest request; ConformanceResponse response; request.set_json_payload(input_json); + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); string effective_test_name = - ConformanceLevelToString(level) + ".JsonInput." + test_name; + ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name; // We don't expect output, but if the program erroneously accepts the protobuf // we let it send its response as this. We must not leave it unspecified. @@ -503,7 +571,7 @@ void ConformanceTestSuite::ExpectParseFailureForJson( void ConformanceTestSuite::ExpectSerializeFailureForJson( const string& test_name, ConformanceLevel level, const string& text_format) { - TestAllTypes payload_message; + TestAllTypesProto3 payload_message; GOOGLE_CHECK( TextFormat::ParseFromString(text_format, &payload_message)) << "Failed to parse: " << text_format; @@ -511,6 +579,7 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson( ConformanceRequest request; ConformanceResponse response; request.set_protobuf_payload(payload_message.SerializeAsString()); + request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); string effective_test_name = ConformanceLevelToString(level) + "." + test_name + ".JsonOutput"; request.set_requested_output_format(conformance::JSON); @@ -526,6 +595,7 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson( } } +//TODO: proto2? void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { // Incomplete values for each wire type. static const string incompletes[6] = { @@ -537,8 +607,8 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { string("abc") // 32BIT }; - uint32_t fieldnum = GetFieldNumberForType(type, false); - uint32_t rep_fieldnum = GetFieldNumberForType(type, true); + const FieldDescriptor* field = GetFieldForType(type, false, true); + const FieldDescriptor* rep_field = GetFieldForType(type, true, true); WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( static_cast<WireFormatLite::FieldType>(type)); const string& incomplete = incompletes[wire_type]; @@ -546,11 +616,11 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { UpperCase(string(".") + FieldDescriptor::TypeName(type)); ExpectParseFailureForProto( - tag(fieldnum, wire_type), + tag(field->number(), wire_type), "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED); ExpectParseFailureForProto( - tag(rep_fieldnum, wire_type), + tag(rep_field->number(), wire_type), "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED); ExpectParseFailureForProto( @@ -558,11 +628,11 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { "PrematureEofBeforeUnknownValue" + type_name, REQUIRED); ExpectParseFailureForProto( - cat( tag(fieldnum, wire_type), incomplete ), + cat( tag(field->number(), wire_type), incomplete ), "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED); ExpectParseFailureForProto( - cat( tag(rep_fieldnum, wire_type), incomplete ), + cat( tag(rep_field->number(), wire_type), incomplete ), "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED); ExpectParseFailureForProto( @@ -571,12 +641,12 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { ExpectParseFailureForProto( - cat( tag(fieldnum, wire_type), varint(1) ), + cat( tag(field->number(), wire_type), varint(1) ), "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name, REQUIRED); ExpectParseFailureForProto( - cat( tag(rep_fieldnum, wire_type), varint(1) ), + cat( tag(rep_field->number(), wire_type), varint(1) ), "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name, REQUIRED); @@ -591,7 +661,7 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), incompletes[WireFormatLite::WIRETYPE_VARINT] ); ExpectHardParseFailureForProto( - cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), varint(incomplete_submsg.size()), incomplete_submsg ), "PrematureEofInSubmessageValue" + type_name, REQUIRED); @@ -601,19 +671,53 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { // Packed region ends in the middle of a value. ExpectHardParseFailureForProto( - cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(incomplete.size()), - incomplete ), + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + varint(incomplete.size()), incomplete), "PrematureEofInPackedFieldValue" + type_name, REQUIRED); // EOF in the middle of packed region. ExpectParseFailureForProto( - cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(1) ), + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + varint(1)), "PrematureEofInPackedField" + type_name, REQUIRED); } } +void ConformanceTestSuite::TestValidDataForType( + FieldDescriptor::Type type, + std::vector<std::pair<std::string, std::string>> values) { + for (int isProto3 = 0; isProto3 < 2; isProto3++) { + const string type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(type)); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(type)); + const FieldDescriptor* field = GetFieldForType(type, false, isProto3); + const FieldDescriptor* rep_field = GetFieldForType(type, true, isProto3); + + RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED, + cat(tag(field->number(), wire_type), values[0].first), + field->name() + ": " + values[0].second, isProto3); + + string proto; + string text = field->name() + ": " + values.back().second; + for (size_t i = 0; i < values.size(); i++) { + proto += cat(tag(field->number(), wire_type), values[i].first); + } + RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED, + proto, text, isProto3); + + proto.clear(); + text.clear(); + + for (size_t i = 0; i < values.size(); i++) { + proto += cat(tag(rep_field->number(), wire_type), values[i].first); + text += rep_field->name() + ": " + values[i].second + " "; + } + RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED, + proto, text, isProto3); + } +} + void ConformanceTestSuite::SetFailureList(const string& filename, const vector<string>& failure_list) { failure_list_filename_ = filename; @@ -622,7 +726,7 @@ void ConformanceTestSuite::SetFailureList(const string& filename, std::inserter(expected_to_fail_, expected_to_fail_.end())); } -bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, +bool ConformanceTestSuite::CheckSetEmpty(const std::set<string>& set_to_check, const std::string& write_to_file, const std::string& msg) { if (set_to_check.empty()) { @@ -630,7 +734,7 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, } else { StringAppendF(&output_, "\n"); StringAppendF(&output_, "%s\n\n", msg.c_str()); - for (set<string>::const_iterator iter = set_to_check.begin(); + for (std::set<string>::const_iterator iter = set_to_check.begin(); iter != set_to_check.end(); ++iter) { StringAppendF(&output_, " %s\n", iter->c_str()); } @@ -639,7 +743,7 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, if (!write_to_file.empty()) { std::ofstream os(write_to_file); if (os) { - for (set<string>::const_iterator iter = set_to_check.begin(); + for (std::set<string>::const_iterator iter = set_to_check.begin(); iter != set_to_check.end(); ++iter) { os << *iter << "\n"; } @@ -653,6 +757,60 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, } } +// TODO: proto2? +void ConformanceTestSuite::TestIllegalTags() { + // field num 0 is illegal + string nullfield[] = { + "\1DEADBEEF", + "\2\1\1", + "\3\4", + "\5DEAD" + }; + for (int i = 0; i < 4; i++) { + string name = "IllegalZeroFieldNum_Case_0"; + name.back() += i; + ExpectParseFailureForProto(nullfield[i], name, REQUIRED); + } +} +template <class MessageType> +void ConformanceTestSuite::TestOneofMessage (MessageType &message, + bool isProto3) { + message.set_oneof_uint32(0); + RunValidProtobufTestWithMessage( + "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", isProto3); + message.mutable_oneof_nested_message()->set_a(0); + RunValidProtobufTestWithMessage( + "OneofZeroMessage", RECOMMENDED, &message, + isProto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}", + isProto3); + message.mutable_oneof_nested_message()->set_a(1); + RunValidProtobufTestWithMessage( + "OneofZeroMessageSetTwice", RECOMMENDED, &message, + "oneof_nested_message: {a: 1}", + isProto3); + message.set_oneof_string(""); + RunValidProtobufTestWithMessage( + "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", isProto3); + message.set_oneof_bytes(""); + RunValidProtobufTestWithMessage( + "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", isProto3); + message.set_oneof_bool(false); + RunValidProtobufTestWithMessage( + "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", isProto3); + message.set_oneof_uint64(0); + RunValidProtobufTestWithMessage( + "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", isProto3); + message.set_oneof_float(0.0f); + RunValidProtobufTestWithMessage( + "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", isProto3); + message.set_oneof_double(0.0); + RunValidProtobufTestWithMessage( + "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", isProto3); + message.set_oneof_enum(MessageType::FOO); + RunValidProtobufTestWithMessage( + "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", isProto3); +} + bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, std::string* output) { runner_ = runner; @@ -664,7 +822,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, unexpected_succeeding_tests_.clear(); type_resolver_.reset(NewTypeResolverForDescriptorPool( kTypeUrlPrefix, DescriptorPool::generated_pool())); - type_url_ = GetTypeUrl(TestAllTypes::descriptor()); + type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor()); output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n"; @@ -673,6 +831,99 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i)); } + TestIllegalTags(); + + int64 kInt64Min = -9223372036854775808ULL; + int64 kInt64Max = 9223372036854775807ULL; + uint64 kUint64Max = 18446744073709551615ULL; + int32 kInt32Max = 2147483647; + int32 kInt32Min = -2147483648; + uint32 kUint32Max = 4294967295UL; + + TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, { + {dbl(0.1), "0.1"}, + {dbl(1.7976931348623157e+308), "1.7976931348623157e+308"}, + {dbl(2.22507385850720138309e-308), "2.22507385850720138309e-308"} + }); + TestValidDataForType(FieldDescriptor::TYPE_FLOAT, { + {flt(0.1), "0.1"}, + {flt(1.00000075e-36), "1.00000075e-36"}, + {flt(3.402823e+38), "3.402823e+38"}, // 3.40282347e+38 + {flt(1.17549435e-38f), "1.17549435e-38"} + }); + TestValidDataForType(FieldDescriptor::TYPE_INT64, { + {varint(12345), "12345"}, + {varint(kInt64Max), std::to_string(kInt64Max)}, + {varint(kInt64Min), std::to_string(kInt64Min)} + }); + TestValidDataForType(FieldDescriptor::TYPE_UINT64, { + {varint(12345), "12345"}, + {varint(kUint64Max), std::to_string(kUint64Max)}, + {varint(0), "0"} + }); + TestValidDataForType(FieldDescriptor::TYPE_INT32, { + {varint(12345), "12345"}, + {longvarint(12345, 2), "12345"}, + {longvarint(12345, 7), "12345"}, + {varint(kInt32Max), std::to_string(kInt32Max)}, + {varint(kInt32Min), std::to_string(kInt32Min)}, + {varint(1LL << 33), std::to_string(static_cast<int32>(1LL << 33))}, + {varint((1LL << 33) - 1), + std::to_string(static_cast<int32>((1LL << 33) - 1))}, + }); + TestValidDataForType(FieldDescriptor::TYPE_UINT32, { + {varint(12345), "12345"}, + {longvarint(12345, 2), "12345"}, + {longvarint(12345, 7), "12345"}, + {varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX + {varint(0), "0"}, + {varint(1LL << 33), std::to_string(static_cast<uint32>(1LL << 33))}, + {varint((1LL << 33) - 1), + std::to_string(static_cast<uint32>((1LL << 33) - 1))}, + }); + TestValidDataForType(FieldDescriptor::TYPE_FIXED64, { + {u64(12345), "12345"}, + {u64(kUint64Max), std::to_string(kUint64Max)}, + {u64(0), "0"} + }); + TestValidDataForType(FieldDescriptor::TYPE_FIXED32, { + {u32(12345), "12345"}, + {u32(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX + {u32(0), "0"} + }); + TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, { + {u64(12345), "12345"}, + {u64(kInt64Max), std::to_string(kInt64Max)}, + {u64(kInt64Min), std::to_string(kInt64Min)} + }); + TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, { + {u32(12345), "12345"}, + {u32(kInt32Max), std::to_string(kInt32Max)}, + {u32(kInt32Min), std::to_string(kInt32Min)} + }); + TestValidDataForType(FieldDescriptor::TYPE_BOOL, { + {varint(1), "true"}, + {varint(0), "false"}, + {varint(12345678), "true"} + }); + TestValidDataForType(FieldDescriptor::TYPE_SINT32, { + {zz32(12345), "12345"}, + {zz32(kInt32Max), std::to_string(kInt32Max)}, + {zz32(kInt32Min), std::to_string(kInt32Min)} + }); + TestValidDataForType(FieldDescriptor::TYPE_SINT64, { + {zz64(12345), "12345"}, + {zz64(kInt64Max), std::to_string(kInt64Max)}, + {zz64(kInt64Min), std::to_string(kInt64Min)} + }); + + // TODO(haberman): + // TestValidDataForType(FieldDescriptor::TYPE_STRING + // TestValidDataForType(FieldDescriptor::TYPE_GROUP + // TestValidDataForType(FieldDescriptor::TYPE_MESSAGE + // TestValidDataForType(FieldDescriptor::TYPE_BYTES + // TestValidDataForType(FieldDescriptor::TYPE_ENUM + RunValidJsonTest("HelloWorld", REQUIRED, "{\"optionalString\":\"Hello, World!\"}", "optional_string: 'Hello, World!'"); @@ -685,7 +936,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, R"({ "fieldname1": 1, "fieldName2": 2, - "fieldName3": 3, + "FieldName3": 3, "fieldName4": 4 })", R"( @@ -725,12 +976,12 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, RunValidJsonTest( "FieldNameWithDoubleUnderscores", RECOMMENDED, R"({ - "fieldName13": 13, - "fieldName14": 14, + "FieldName13": 13, + "FieldName14": 14, "fieldName15": 15, "fieldName16": 16, "fieldName17": 17, - "fieldName18": 18 + "FieldName18": 18 })", R"( __field_name13: 13 @@ -873,21 +1124,19 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "optionalNestedMessage": {a: 1}, "optional_nested_message": {} })"); - // NOTE: The spec for JSON support is still being sorted out, these may not - // all be correct. // Serializers should use lowerCamelCase by default. RunValidJsonTestWithValidator( "FieldNameInLowerCamelCase", REQUIRED, R"({ "fieldname1": 1, "fieldName2": 2, - "fieldName3": 3, + "FieldName3": 3, "fieldName4": 4 })", [](const Json::Value& value) { return value.isMember("fieldname1") && value.isMember("fieldName2") && - value.isMember("fieldName3") && + value.isMember("FieldName3") && value.isMember("fieldName4"); }); RunValidJsonTestWithValidator( @@ -921,20 +1170,20 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, RunValidJsonTestWithValidator( "FieldNameWithDoubleUnderscores", RECOMMENDED, R"({ - "fieldName13": 13, - "fieldName14": 14, + "FieldName13": 13, + "FieldName14": 14, "fieldName15": 15, "fieldName16": 16, "fieldName17": 17, - "fieldName18": 18 + "FieldName18": 18 })", [](const Json::Value& value) { - return value.isMember("fieldName13") && - value.isMember("fieldName14") && + return value.isMember("FieldName13") && + value.isMember("FieldName14") && value.isMember("fieldName15") && value.isMember("fieldName16") && value.isMember("fieldName17") && - value.isMember("fieldName18"); + value.isMember("FieldName18"); }); // Integer fields. @@ -1072,7 +1321,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "Int32FieldNegativeWithLeadingZero", REQUIRED, R"({"optionalInt32": -01})"); // String values must follow the same syntax rule. Specifically leading - // or traling spaces are not allowed. + // or trailing spaces are not allowed. ExpectParseFailureForJson( "Int32FieldLeadingSpace", REQUIRED, R"({"optionalInt32": " 1"})"); @@ -1169,7 +1418,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "optional_float: -inf"); // Non-cannonical Nan will be correctly normalized. { - TestAllTypes message; + TestAllTypesProto3 message; // IEEE floating-point standard 32-bit quiet NaN: // 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx message.set_optional_float( @@ -1241,7 +1490,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "optional_double: -inf"); // Non-cannonical Nan will be correctly normalized. { - TestAllTypes message; + TestAllTypesProto3 message; message.set_optional_double( WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL)); RunValidJsonTestWithProtobufInput( @@ -1356,9 +1605,10 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "BytesField", REQUIRED, R"({"optionalBytes": "AQI="})", R"(optional_bytes: "\x01\x02")"); - ExpectParseFailureForJson( - "BytesFieldInvalidBase64Characters", REQUIRED, - R"({"optionalBytes": "-_=="})"); + RunValidJsonTest( + "BytesFieldBase64Url", RECOMMENDED, + R"({"optionalBytes": "-_"})", + R"(optional_bytes: "\xfb")"); // Message fields. RunValidJsonTest( @@ -1371,36 +1621,10 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "OneofFieldDuplicate", REQUIRED, R"({"oneofUint32": 1, "oneofString": "test"})"); // Ensure zero values for oneof make it out/backs. - { - TestAllTypes message; - message.set_oneof_uint32(0); - RunValidProtobufTest( - "OneofZeroUint32", RECOMMENDED, message, "oneof_uint32: 0"); - message.mutable_oneof_nested_message()->set_a(0); - RunValidProtobufTest( - "OneofZeroMessage", RECOMMENDED, message, "oneof_nested_message: {}"); - message.set_oneof_string(""); - RunValidProtobufTest( - "OneofZeroString", RECOMMENDED, message, "oneof_string: \"\""); - message.set_oneof_bytes(""); - RunValidProtobufTest( - "OneofZeroBytes", RECOMMENDED, message, "oneof_bytes: \"\""); - message.set_oneof_bool(false); - RunValidProtobufTest( - "OneofZeroBool", RECOMMENDED, message, "oneof_bool: false"); - message.set_oneof_uint64(0); - RunValidProtobufTest( - "OneofZeroUint64", RECOMMENDED, message, "oneof_uint64: 0"); - message.set_oneof_float(0.0f); - RunValidProtobufTest( - "OneofZeroFloat", RECOMMENDED, message, "oneof_float: 0"); - message.set_oneof_double(0.0); - RunValidProtobufTest( - "OneofZeroDouble", RECOMMENDED, message, "oneof_double: 0"); - message.set_oneof_enum(TestAllTypes::FOO); - RunValidProtobufTest( - "OneofZeroEnum", RECOMMENDED, message, "oneof_enum: FOO"); - } + TestAllTypesProto3 messageProto3; + TestAllTypesProto2 messageProto2; + TestOneofMessage(messageProto3, true); + TestOneofMessage(messageProto2, false); RunValidJsonTest( "OneofZeroUint32", RECOMMENDED, R"({"oneofUint32": 0})", "oneof_uint32: 0"); @@ -2050,13 +2274,13 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "Any", REQUIRED, R"({ "optionalAny": { - "@type": "type.googleapis.com/conformance.TestAllTypes", + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", "optionalInt32": 12345 } })", R"( optional_any: { - [type.googleapis.com/conformance.TestAllTypes] { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { optional_int32: 12345 } } @@ -2067,7 +2291,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Any", "value": { - "@type": "type.googleapis.com/conformance.TestAllTypes", + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", "optionalInt32": 12345 } } @@ -2075,7 +2299,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, R"( optional_any: { [type.googleapis.com/google.protobuf.Any] { - [type.googleapis.com/conformance.TestAllTypes] { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { optional_int32: 12345 } } @@ -2087,12 +2311,12 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, R"({ "optionalAny": { "optionalInt32": 12345, - "@type": "type.googleapis.com/conformance.TestAllTypes" + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" } })", R"( optional_any: { - [type.googleapis.com/conformance.TestAllTypes] { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { optional_int32: 12345 } } |