Added group roundtrip tests and fixed any issues discovered
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
index fd2d52a..e6a685d 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -348,6 +348,56 @@
Assert.AreEqual(message, parsed);
}
+ [Test]
+ public void RoundTrip_Groups()
+ {
+ var message = new Proto2.TestAllTypes
+ {
+ OptionalGroup = new Proto2.TestAllTypes.Types.OptionalGroup
+ {
+ A = 10
+ },
+ RepeatedGroup =
+ {
+ new Proto2.TestAllTypes.Types.RepeatedGroup { A = 10 },
+ new Proto2.TestAllTypes.Types.RepeatedGroup { A = 20 },
+ new Proto2.TestAllTypes.Types.RepeatedGroup { A = 30 }
+ }
+ };
+
+ byte[] bytes = message.ToByteArray();
+ Proto2.TestAllTypes parsed = Proto2.TestAllTypes.Parser.ParseFrom(bytes);
+ Assert.AreEqual(message, parsed);
+ }
+
+ [Test]
+ public void RoundTrip_ExtensionGroups()
+ {
+ var message = new Proto2.TestAllExtensions();
+ message.SetExtension(Proto2.UnittestExtensions.OptionalGroupExtension, new Proto2.OptionalGroup_extension { A = 10 });
+ message.GetOrRegisterExtension(Proto2.UnittestExtensions.RepeatedGroupExtension).AddRange(new[]
+ {
+ new Proto2.RepeatedGroup_extension { A = 10 },
+ new Proto2.RepeatedGroup_extension { A = 20 },
+ new Proto2.RepeatedGroup_extension { A = 30 }
+ });
+
+ byte[] bytes = message.ToByteArray();
+ Proto2.TestAllExtensions extendable_parsed = Proto2.TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { Proto2.UnittestExtensions.OptionalGroupExtension, Proto2.UnittestExtensions.RepeatedGroupExtension }).ParseFrom(bytes);
+ Assert.AreEqual(message, extendable_parsed);
+ }
+
+ [Test]
+ public void RoundTrip_NestedExtensionGroup()
+ {
+ var message = new Proto2.TestGroupExtension();
+ message.SetExtension(Proto2.TestNestedExtension.Extensions.OptionalGroupExtension, new Proto2.TestNestedExtension.Types.OptionalGroup_extension { A = 10 });
+
+ byte[] bytes = message.ToByteArray();
+ Proto2.TestGroupExtension extendable_parsed = Proto2.TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { Proto2.TestNestedExtension.Extensions.OptionalGroupExtension }).ParseFrom(bytes);
+ Assert.AreEqual(message, extendable_parsed);
+ }
+
// Note that not every map within map_unittest_proto3 is used. They all go through very
// similar code paths. The fact that all maps are present is validation that we have codecs
// for every type.
diff --git a/csharp/src/Google.Protobuf.Test/SampleMessages.cs b/csharp/src/Google.Protobuf.Test/SampleMessages.cs
index 68f7e27..0c37814 100644
--- a/csharp/src/Google.Protobuf.Test/SampleMessages.cs
+++ b/csharp/src/Google.Protobuf.Test/SampleMessages.cs
@@ -123,6 +123,7 @@
OptionalString = "test",
OptionalUint32 = UInt32.MaxValue,
OptionalUint64 = UInt64.MaxValue,
+ OptionalGroup = new Proto2.TestAllTypes.Types.OptionalGroup { A = 10 },
RepeatedBool = { true, false },
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
RepeatedDouble = { -12.25, 23.5 },
@@ -144,6 +145,7 @@
RepeatedString = { "foo", "bar" },
RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue },
RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue },
+ RepeatedGroup = { new Proto2.TestAllTypes.Types.RepeatedGroup { A = 10 }, new Proto2.TestAllTypes.Types.RepeatedGroup { A = 20 } },
OneofString = "Oneof string"
};
}
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test/TestProtos/Unittest.cs
index 13effe5..1043d73 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/Unittest.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/Unittest.cs
@@ -5406,6 +5406,8 @@
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
+ case 132:
+ return;
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
@@ -5550,6 +5552,8 @@
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
+ case 372:
+ return;
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
@@ -6279,6 +6283,8 @@
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
+ case 132:
+ return;
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index 827bc71..d8095c8 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -148,6 +148,10 @@
{
var sizeCalculator = codec.ValueSizeCalculator;
int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
+ if (codec.EndTag != 0)
+ {
+ size += count * CodedOutputStream.ComputeRawVarint32Size(codec.EndTag);
+ }
for (int i = 0; i < count; i++)
{
size += sizeCalculator(array[i]);
diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs
index 90d3113..c2c4b57 100644
--- a/csharp/src/Google.Protobuf/FieldCodec.cs
+++ b/csharp/src/Google.Protobuf/FieldCodec.cs
@@ -731,6 +731,7 @@
ValueSizeCalculator = sizeCalculator;
FixedSize = 0;
Tag = tag;
+ EndTag = endTag;
DefaultValue = defaultValue;
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
if (endTag != 0)