diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc index 7c982f931..8e2ff862e 100644 --- a/conformance/binary_json_conformance_suite.cc +++ b/conformance/binary_json_conformance_suite.cc @@ -149,10 +149,6 @@ string tag(uint32_t fieldnum, char wire_type) { return varint((fieldnum << 3) | wire_type); } -string submsg(uint32_t fn, const string& buf) { - return cat( tag(fn, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(buf) ); -} - #define UNKNOWN_FIELD 666 const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, @@ -594,17 +590,24 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType( const FieldDescriptor* field = GetFieldForType(type, false, is_proto3); const FieldDescriptor* rep_field = GetFieldForType(type, true, is_proto3); - RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED, - cat(tag(field->number(), wire_type), values[0].first), - field->name() + ": " + values[0].second, is_proto3); + for (size_t i = 0; i < values.size(); i++) { + RunValidProtobufTest(StrCat("ValidDataScalar", type_name, "[", i, "]"), + REQUIRED, + cat(tag(field->number(), wire_type), values[0].first), + field->name() + ": " + values[0].second, is_proto3); + } 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, is_proto3); + // For scalar message fields, repeated values are merged, which is tested + // separately. + if (type != FieldDescriptor::TYPE_MESSAGE) { + RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED, + proto, text, is_proto3); + } proto.clear(); text.clear(); @@ -618,6 +621,48 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType( } } +void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() { + std::vector values = { + delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat( + tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234), + tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1234), + tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234) + )))), + delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat( + tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321), + tag(3, WireFormatLite::WIRETYPE_VARINT), varint(4321), + tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321) + )))), + }; + + const std::string expected = + R"({ + corecursive: { + optional_int32: 4321, + optional_int64: 1234, + optional_uint32: 4321, + repeated_int32: [1234, 4321], + } + })"; + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + string proto; + const FieldDescriptor* field = + GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false, is_proto3); + for (size_t i = 0; i < values.size(); i++) { + proto += + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + values[i]); + } + + RunValidProtobufTest( + "RepeatedScalarMessageMerge", REQUIRED, proto, + field->name() + ": " + expected, is_proto3); + } +} + // TODO: proto2? void BinaryAndJsonConformanceSuite::TestIllegalTags() { // field num 0 is illegal @@ -810,10 +855,15 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() { {varint(2), "BAZ"}, {varint(-1), "NEG"}, }); + TestValidDataForRepeatedScalarMessage(); + TestValidDataForType(FieldDescriptor::TYPE_MESSAGE, { + {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))), + "{a: 1234}"}, + {delim(""), "{}"}, + }); // TODO(haberman): // TestValidDataForType(FieldDescriptor::TYPE_GROUP - // TestValidDataForType(FieldDescriptor::TYPE_MESSAGE RunValidJsonTest("HelloWorld", REQUIRED, "{\"optionalString\":\"Hello, World!\"}", diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h index 7a03545fa..e74c956e9 100644 --- a/conformance/binary_json_conformance_suite.h +++ b/conformance/binary_json_conformance_suite.h @@ -109,6 +109,7 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { void TestValidDataForType( google::protobuf::FieldDescriptor::Type, std::vector> values); + void TestValidDataForRepeatedScalarMessage(); std::unique_ptr type_resolver_; diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt index df70a9b02..28e16943c 100644 --- a/conformance/failure_list_js.txt +++ b/conformance/failure_list_js.txt @@ -12,3 +12,4 @@ Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt index 28ca461d4..f7ed13734 100644 --- a/conformance/failure_list_php.txt +++ b/conformance/failure_list_php.txt @@ -18,3 +18,5 @@ Required.Proto3.JsonInput.Uint64FieldNotInteger Required.Proto3.JsonInput.Int32FieldLeadingSpace Required.Proto3.JsonInput.OneofFieldDuplicate Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput