|
@@ -149,6 +149,69 @@ string tag(uint32_t fieldnum, char wire_type) {
|
|
|
return varint((fieldnum << 3) | wire_type);
|
|
|
}
|
|
|
|
|
|
+string GetDefaultValue(FieldDescriptor::Type type) {
|
|
|
+ switch (type) {
|
|
|
+ case FieldDescriptor::TYPE_INT32:
|
|
|
+ case FieldDescriptor::TYPE_INT64:
|
|
|
+ case FieldDescriptor::TYPE_UINT32:
|
|
|
+ case FieldDescriptor::TYPE_UINT64:
|
|
|
+ case FieldDescriptor::TYPE_ENUM:
|
|
|
+ case FieldDescriptor::TYPE_BOOL:
|
|
|
+ return varint(0);
|
|
|
+ case FieldDescriptor::TYPE_SINT32:
|
|
|
+ return zz32(0);
|
|
|
+ case FieldDescriptor::TYPE_SINT64:
|
|
|
+ return zz64(0);
|
|
|
+ case FieldDescriptor::TYPE_FIXED32:
|
|
|
+ case FieldDescriptor::TYPE_SFIXED32:
|
|
|
+ return u32(0);
|
|
|
+ case FieldDescriptor::TYPE_FIXED64:
|
|
|
+ case FieldDescriptor::TYPE_SFIXED64:
|
|
|
+ return u64(0);
|
|
|
+ case FieldDescriptor::TYPE_FLOAT:
|
|
|
+ return flt(0);
|
|
|
+ case FieldDescriptor::TYPE_DOUBLE:
|
|
|
+ return dbl(0);
|
|
|
+ case FieldDescriptor::TYPE_STRING:
|
|
|
+ case FieldDescriptor::TYPE_BYTES:
|
|
|
+ case FieldDescriptor::TYPE_MESSAGE:
|
|
|
+ return delim("");
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+}
|
|
|
+
|
|
|
+string GetNonDefaultValue(FieldDescriptor::Type type) {
|
|
|
+ switch (type) {
|
|
|
+ case FieldDescriptor::TYPE_INT32:
|
|
|
+ case FieldDescriptor::TYPE_INT64:
|
|
|
+ case FieldDescriptor::TYPE_UINT32:
|
|
|
+ case FieldDescriptor::TYPE_UINT64:
|
|
|
+ case FieldDescriptor::TYPE_ENUM:
|
|
|
+ case FieldDescriptor::TYPE_BOOL:
|
|
|
+ return varint(1);
|
|
|
+ case FieldDescriptor::TYPE_SINT32:
|
|
|
+ return zz32(1);
|
|
|
+ case FieldDescriptor::TYPE_SINT64:
|
|
|
+ return zz64(1);
|
|
|
+ case FieldDescriptor::TYPE_FIXED32:
|
|
|
+ case FieldDescriptor::TYPE_SFIXED32:
|
|
|
+ return u32(1);
|
|
|
+ case FieldDescriptor::TYPE_FIXED64:
|
|
|
+ case FieldDescriptor::TYPE_SFIXED64:
|
|
|
+ return u64(1);
|
|
|
+ case FieldDescriptor::TYPE_FLOAT:
|
|
|
+ return flt(1);
|
|
|
+ case FieldDescriptor::TYPE_DOUBLE:
|
|
|
+ return dbl(1);
|
|
|
+ case FieldDescriptor::TYPE_STRING:
|
|
|
+ case FieldDescriptor::TYPE_BYTES:
|
|
|
+ return delim("a");
|
|
|
+ case FieldDescriptor::TYPE_MESSAGE:
|
|
|
+ return delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)));
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+}
|
|
|
+
|
|
|
#define UNKNOWN_FIELD 666
|
|
|
|
|
|
enum class Packed {
|
|
@@ -189,6 +252,34 @@ const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
+const FieldDescriptor* GetFieldForMapType(
|
|
|
+ FieldDescriptor::Type key_type,
|
|
|
+ FieldDescriptor::Type value_type,
|
|
|
+ bool is_proto3) {
|
|
|
+ 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->is_map()) {
|
|
|
+ const Descriptor* map_entry = f->message_type();
|
|
|
+ const FieldDescriptor* key = map_entry->field(0);
|
|
|
+ const FieldDescriptor* value = map_entry->field(1);
|
|
|
+ if (key->type() == key_type && value->type() == value_type) {
|
|
|
+ return f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const string proto_string = is_proto3 ? "Proto3" : "Proto2";
|
|
|
+ GOOGLE_LOG(FATAL) << "Couldn't find map field with type: "
|
|
|
+ << FieldDescriptor::TypeName(key_type)
|
|
|
+ << " and "
|
|
|
+ << FieldDescriptor::TypeName(key_type)
|
|
|
+ << " for "
|
|
|
+ << proto_string.c_str();
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
string UpperCase(string str) {
|
|
|
for (int i = 0; i < str.size(); i++) {
|
|
|
str[i] = toupper(str[i]);
|
|
@@ -836,6 +927,190 @@ void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void BinaryAndJsonConformanceSuite::TestValidDataForMapType(
|
|
|
+ FieldDescriptor::Type key_type,
|
|
|
+ FieldDescriptor::Type value_type) {
|
|
|
+ const string key_type_name =
|
|
|
+ UpperCase(string(".") + FieldDescriptor::TypeName(key_type));
|
|
|
+ const string value_type_name =
|
|
|
+ UpperCase(string(".") + FieldDescriptor::TypeName(value_type));
|
|
|
+ WireFormatLite::WireType key_wire_type =
|
|
|
+ WireFormatLite::WireTypeForFieldType(
|
|
|
+ static_cast<WireFormatLite::FieldType>(key_type));
|
|
|
+ WireFormatLite::WireType value_wire_type =
|
|
|
+ WireFormatLite::WireTypeForFieldType(
|
|
|
+ static_cast<WireFormatLite::FieldType>(value_type));
|
|
|
+
|
|
|
+ string key1_data =
|
|
|
+ cat(tag(1, key_wire_type), GetDefaultValue(key_type));
|
|
|
+ string value1_data =
|
|
|
+ cat(tag(2, value_wire_type), GetDefaultValue(value_type));
|
|
|
+ string key2_data =
|
|
|
+ cat(tag(1, key_wire_type), GetNonDefaultValue(key_type));
|
|
|
+ string value2_data =
|
|
|
+ cat(tag(2, value_wire_type), GetNonDefaultValue(value_type));
|
|
|
+
|
|
|
+ for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
|
|
|
+ const FieldDescriptor* field =
|
|
|
+ GetFieldForMapType(key_type, value_type, is_proto3);
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with default key and value.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key1_data, value1_data)));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".Default"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with missing default key and value.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(""));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".MissingDefault"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with non-default key and value.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key2_data, value2_data)));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".NonDefault"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with unordered key and value.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(value2_data, key2_data)));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".Unordered"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with duplicate key.
|
|
|
+ string proto1 = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key2_data, value1_data)));
|
|
|
+ string proto2 = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key2_data, value2_data)));
|
|
|
+ string proto = cat(proto1, proto2);
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto2);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".DuplicateKey"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with duplicate key in map entry.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key1_data, key2_data, value2_data)));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".DuplicateKeyInMapEntry"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // Tests map with duplicate value in map entry.
|
|
|
+ string proto = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key2_data, value1_data, value2_data)));
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ StrCat("ValidDataMap",
|
|
|
+ key_type_name,
|
|
|
+ value_type_name,
|
|
|
+ ".DuplicateValueInMapEntry"),
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void BinaryAndJsonConformanceSuite::TestOverwriteMessageValueMap() {
|
|
|
+ string key_data =
|
|
|
+ cat(tag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(""));
|
|
|
+ string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1));
|
|
|
+ string field2_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1));
|
|
|
+ string field31_data = cat(tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1));
|
|
|
+ string submsg1_data = delim(cat(field1_data, field31_data));
|
|
|
+ string submsg2_data = delim(cat(field2_data, field31_data));
|
|
|
+ string value1_data =
|
|
|
+ cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ submsg1_data)));
|
|
|
+ string value2_data =
|
|
|
+ cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ submsg2_data)));
|
|
|
+
|
|
|
+ for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
|
|
|
+ const FieldDescriptor* field =
|
|
|
+ GetFieldForMapType(
|
|
|
+ FieldDescriptor::TYPE_STRING,
|
|
|
+ FieldDescriptor::TYPE_MESSAGE, is_proto3);
|
|
|
+
|
|
|
+ string proto1 = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key_data, value1_data)));
|
|
|
+ string proto2 = cat(tag(field->number(),
|
|
|
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
|
|
+ delim(cat(key_data, value2_data)));
|
|
|
+ string proto = cat(proto1, proto2);
|
|
|
+ std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
|
|
|
+ test_message->MergeFromString(proto2);
|
|
|
+ string text = test_message->DebugString();
|
|
|
+ RunValidProtobufTest(
|
|
|
+ "ValidDataMap.STRING.MESSAGE.MergeValue",
|
|
|
+ REQUIRED, proto, text, is_proto3);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void BinaryAndJsonConformanceSuite::TestIllegalTags() {
|
|
|
// field num 0 is illegal
|
|
|
string nullfield[] = {
|
|
@@ -1040,6 +1315,60 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
|
|
|
delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
|
|
|
});
|
|
|
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_INT32,
|
|
|
+ FieldDescriptor::TYPE_INT32);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_INT64,
|
|
|
+ FieldDescriptor::TYPE_INT64);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_UINT32,
|
|
|
+ FieldDescriptor::TYPE_UINT32);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_UINT64,
|
|
|
+ FieldDescriptor::TYPE_UINT64);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_SINT32,
|
|
|
+ FieldDescriptor::TYPE_SINT32);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_SINT64,
|
|
|
+ FieldDescriptor::TYPE_SINT64);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_FIXED32,
|
|
|
+ FieldDescriptor::TYPE_FIXED32);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_FIXED64,
|
|
|
+ FieldDescriptor::TYPE_FIXED64);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_SFIXED32,
|
|
|
+ FieldDescriptor::TYPE_SFIXED32);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_SFIXED64,
|
|
|
+ FieldDescriptor::TYPE_SFIXED64);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_INT32,
|
|
|
+ FieldDescriptor::TYPE_FLOAT);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_INT32,
|
|
|
+ FieldDescriptor::TYPE_DOUBLE);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_BOOL,
|
|
|
+ FieldDescriptor::TYPE_BOOL);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_STRING,
|
|
|
+ FieldDescriptor::TYPE_STRING);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_STRING,
|
|
|
+ FieldDescriptor::TYPE_BYTES);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_STRING,
|
|
|
+ FieldDescriptor::TYPE_ENUM);
|
|
|
+ TestValidDataForMapType(
|
|
|
+ FieldDescriptor::TYPE_STRING,
|
|
|
+ FieldDescriptor::TYPE_MESSAGE);
|
|
|
+ // Additional test to check overwriting message value map.
|
|
|
+ TestOverwriteMessageValueMap();
|
|
|
+
|
|
|
// TODO(haberman):
|
|
|
// TestValidDataForType(FieldDescriptor::TYPE_GROUP
|
|
|
|