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)