Skip to content

Commit

Permalink
Implement binary conformance test for oneof fields (#6622)
Browse files Browse the repository at this point in the history
* Implement binary conformance test for oneof fields

* Update failure list

* Update failure list for php c extension
  • Loading branch information
TeBoring committed Sep 9, 2019
1 parent 1363bf9 commit 7114d73
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
166 changes: 166 additions & 0 deletions conformance/binary_json_conformance_suite.cc
Expand Up @@ -280,6 +280,25 @@ const FieldDescriptor* GetFieldForMapType(
return nullptr; return nullptr;
} }


const FieldDescriptor* GetFieldForOneofType(
FieldDescriptor::Type type, bool is_proto3, bool exclusive = false) {
const Descriptor* d = is_proto3 ?
TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor();
for (int i = 0; i < d->field_count(); i++) {
const FieldDescriptor* f = d->field(i);
if (f->containing_oneof() && ((f->type() == type) ^ exclusive)) {
return f;
}
}

const string proto_string = is_proto3 ? "Proto3" : "Proto2";
GOOGLE_LOG(FATAL) << "Couldn't find oneof field with type: "
<< FieldDescriptor::TypeName(type)
<< " for "
<< proto_string.c_str();
return nullptr;
}

string UpperCase(string str) { string UpperCase(string str) {
for (int i = 0; i < str.size(); i++) { for (int i = 0; i < str.size(); i++) {
str[i] = toupper(str[i]); str[i] = toupper(str[i]);
Expand Down Expand Up @@ -1111,6 +1130,141 @@ void BinaryAndJsonConformanceSuite::TestOverwriteMessageValueMap() {
} }
} }


void BinaryAndJsonConformanceSuite::TestValidDataForOneofType(
FieldDescriptor::Type type) {
const string type_name =
UpperCase(string(".") + FieldDescriptor::TypeName(type));
WireFormatLite::WireType wire_type =
WireFormatLite::WireTypeForFieldType(
static_cast<WireFormatLite::FieldType>(type));

for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
const FieldDescriptor* field = GetFieldForOneofType(type, is_proto3);
const string default_value =
cat(tag(field->number(), wire_type), GetDefaultValue(type));
const string non_default_value =
cat(tag(field->number(), wire_type), GetNonDefaultValue(type));

{
// Tests oneof with default value.
const string proto = default_value;
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(proto);
string text = test_message->DebugString();

RunValidProtobufTest(StrCat("ValidDataOneof", type_name, ".DefaultValue"),
REQUIRED, proto, text, is_proto3);
RunValidBinaryProtobufTest(
StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"),
RECOMMENDED, proto, proto, is_proto3);
}

{
// Tests oneof with non-default value.
const string proto = non_default_value;
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(proto);
string text = test_message->DebugString();

RunValidProtobufTest(
StrCat("ValidDataOneof", type_name, ".NonDefaultValue"),
REQUIRED, proto, text, is_proto3);
RunValidBinaryProtobufTest(
StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"),
RECOMMENDED, proto, proto, is_proto3);
}

{
// Tests oneof with multiple values of the same field.
const string proto = StrCat(default_value, non_default_value);
const string expected_proto = non_default_value;
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();

RunValidProtobufTest(
StrCat("ValidDataOneof", type_name, ".MultipleValuesForSameField"),
REQUIRED, proto, text, is_proto3);
RunValidBinaryProtobufTest(
StrCat("ValidDataOneofBinary", type_name,
".MultipleValuesForSameField"),
RECOMMENDED, proto, expected_proto, is_proto3);
}

{
// Tests oneof with multiple values of the different fields.
const FieldDescriptor* other_field =
GetFieldForOneofType(type, is_proto3, true);
FieldDescriptor::Type other_type = other_field->type();
WireFormatLite::WireType other_wire_type =
WireFormatLite::WireTypeForFieldType(
static_cast<WireFormatLite::FieldType>(other_type));
const string other_value =
cat(tag(other_field->number(), other_wire_type),
GetDefaultValue(other_type));

const string proto = StrCat(other_value, non_default_value);
const string expected_proto = non_default_value;
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();

RunValidProtobufTest(
StrCat("ValidDataOneof", type_name,
".MultipleValuesForDifferentField"),
REQUIRED, proto, text, is_proto3);
RunValidBinaryProtobufTest(
StrCat("ValidDataOneofBinary", type_name,
".MultipleValuesForDifferentField"),
RECOMMENDED, proto, expected_proto, is_proto3);
}
}
}

void BinaryAndJsonConformanceSuite::TestMergeOneofMessage() {
string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1));
string field2a_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1));
string field2b_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1));
string field89_data = cat(tag(89, WireFormatLite::WIRETYPE_VARINT),
varint(1));
string submsg1_data =
cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(cat(field1_data, field2a_data, field89_data)));
string submsg2_data =
cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(cat(field2b_data, field89_data)));
string merged_data = cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(cat(field1_data, field2b_data,
field89_data, field89_data)));

for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
const FieldDescriptor* field =
GetFieldForOneofType(FieldDescriptor::TYPE_MESSAGE, is_proto3);

string proto1 = cat(tag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(submsg1_data));
string proto2 = cat(tag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(submsg2_data));
string proto = cat(proto1, proto2);
string expected_proto =
cat(tag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(merged_data));

std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();
RunValidProtobufTest(
"ValidDataOneof.MESSAGE.Merge",
REQUIRED, proto, text, is_proto3);
RunValidBinaryProtobufTest(
"ValidDataOneofBinary.MESSAGE.Merge",
RECOMMENDED, proto, expected_proto, is_proto3);
}
}

void BinaryAndJsonConformanceSuite::TestIllegalTags() { void BinaryAndJsonConformanceSuite::TestIllegalTags() {
// field num 0 is illegal // field num 0 is illegal
string nullfield[] = { string nullfield[] = {
Expand Down Expand Up @@ -1369,6 +1523,18 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
// Additional test to check overwriting message value map. // Additional test to check overwriting message value map.
TestOverwriteMessageValueMap(); TestOverwriteMessageValueMap();


TestValidDataForOneofType(FieldDescriptor::TYPE_UINT32);
TestValidDataForOneofType(FieldDescriptor::TYPE_BOOL);
TestValidDataForOneofType(FieldDescriptor::TYPE_UINT64);
TestValidDataForOneofType(FieldDescriptor::TYPE_FLOAT);
TestValidDataForOneofType(FieldDescriptor::TYPE_DOUBLE);
TestValidDataForOneofType(FieldDescriptor::TYPE_STRING);
TestValidDataForOneofType(FieldDescriptor::TYPE_BYTES);
TestValidDataForOneofType(FieldDescriptor::TYPE_ENUM);
TestValidDataForOneofType(FieldDescriptor::TYPE_MESSAGE);
// Additional test to check merging oneof message.
TestMergeOneofMessage();

// TODO(haberman): // TODO(haberman):
// TestValidDataForType(FieldDescriptor::TYPE_GROUP // TestValidDataForType(FieldDescriptor::TYPE_GROUP


Expand Down
3 changes: 3 additions & 0 deletions conformance/binary_json_conformance_suite.h
Expand Up @@ -118,6 +118,9 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
void TestValidDataForMapType( void TestValidDataForMapType(
google::protobuf::FieldDescriptor::Type, google::protobuf::FieldDescriptor::Type,
google::protobuf::FieldDescriptor::Type); google::protobuf::FieldDescriptor::Type);
void TestValidDataForOneofType(
google::protobuf::FieldDescriptor::Type);
void TestMergeOneofMessage();
void TestOverwriteMessageValueMap(); void TestOverwriteMessageValueMap();


std::unique_ptr<google::protobuf::util::TypeResolver> std::unique_ptr<google::protobuf::util::TypeResolver>
Expand Down
3 changes: 3 additions & 0 deletions conformance/failure_list_php.txt
Expand Up @@ -4,6 +4,7 @@ Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Expand Down Expand Up @@ -78,3 +79,5 @@ Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
1 change: 1 addition & 0 deletions conformance/failure_list_php_c.txt
Expand Up @@ -107,3 +107,4 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutp
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput

0 comments on commit 7114d73

Please sign in to comment.