Переглянути джерело

More tests, and a bug fix.

Jon Skeet 17 роки тому
батько
коміт
d6c9495797

+ 192 - 0
csharp/ProtocolBuffers.Test/WireFormatTest.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
 using Google.ProtocolBuffers.Descriptors;
 
@@ -16,5 +17,196 @@ namespace Google.ProtocolBuffers {
       Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.String]);
       Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.Message]);
     }
+
+    [Test]
+    public void Serialization() {
+      TestAllTypes message = TestUtil.GetAllSet();
+
+      ByteString rawBytes = message.ToByteString();
+      Assert.AreEqual(rawBytes.Length, message.SerializedSize);
+
+      TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
+
+      TestUtil.AssertAllFieldsSet(message2);
+    }
+
+    [Test]
+    public void SerializeExtensions() {
+      // TestAllTypes and TestAllExtensions should have compatible wire formats,
+      // so if we serealize a TestAllExtensions then parse it as TestAllTypes
+      // it should work.
+
+      TestAllExtensions message = TestUtil.GetAllExtensionsSet();
+      ByteString rawBytes = message.ToByteString();
+      Assert.AreEqual(rawBytes.Length, message.SerializedSize);
+
+      TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
+
+      TestUtil.AssertAllFieldsSet(message2);
+    }
+
+    [Test]
+    public void ParseExtensions() {
+      // TestAllTypes and TestAllExtensions should have compatible wire formats,
+      // so if we serealize a TestAllTypes then parse it as TestAllExtensions
+      // it should work.
+
+      TestAllTypes message = TestUtil.GetAllSet();
+      ByteString rawBytes = message.ToByteString();
+
+      ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
+      TestUtil.RegisterAllExtensions(registry);
+      registry = registry.AsReadOnly();
+
+      TestAllExtensions message2 =
+        TestAllExtensions.ParseFrom(rawBytes, registry);
+
+      TestUtil.AssertAllExtensionsSet(message2);
+    }
+
+    [Test]
+    public void ExtensionsSerializedSize() {
+      Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize);
+    }
+
+    private void AssertFieldsInOrder(ByteString data) {
+      CodedInputStream input = data.CreateCodedInput();
+      uint previousTag = 0;
+
+      while (true) {
+        uint tag = input.ReadTag();
+        if (tag == 0) {
+          break;
+        }
+
+        Assert.IsTrue(tag > previousTag);
+        previousTag = tag;
+        input.SkipField(tag);
+      }
+    }
+
+    [Test]
+    public void InterleavedFieldsAndExtensions() {
+      // Tests that fields are written in order even when extension ranges
+      // are interleaved with field numbers.
+      ByteString data =
+        TestFieldOrderings.CreateBuilder()
+          .SetMyInt(1)
+          .SetMyString("foo")
+          .SetMyFloat(1.0F)
+          .SetExtension(UnitTestProtoFile.MyExtensionInt, 23)
+          .SetExtension(UnitTestProtoFile.MyExtensionString, "bar")
+          .Build().ToByteString();
+      AssertFieldsInOrder(data);
+
+      MessageDescriptor descriptor = TestFieldOrderings.Descriptor;
+      ByteString dynamic_data =
+        DynamicMessage.CreateBuilder(TestFieldOrderings.Descriptor)
+          .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_int"), 1L)
+          .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_string"), "foo")
+          .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_float"), 1.0F)
+          .SetField(UnitTestProtoFile.MyExtensionInt.Descriptor, 23)
+          .SetField(UnitTestProtoFile.MyExtensionString.Descriptor, "bar")
+          .WeakBuild().ToByteString();
+      AssertFieldsInOrder(dynamic_data);
+    }
+
+    private const int UnknownTypeId = 1550055;
+    private static readonly int TypeId1 = TestMessageSetExtension1.Descriptor.Extensions[0].FieldNumber;
+    private static readonly int TypeId2 = TestMessageSetExtension2.Descriptor.Extensions[0].FieldNumber;
+
+    [Test]
+    public void SerializeMessageSet() {
+      // Set up a TestMessageSet with two known messages and an unknown one.
+      TestMessageSet messageSet =
+        TestMessageSet.CreateBuilder()
+          .SetExtension(
+            TestMessageSetExtension1.Types.MessageSetExtension,
+            TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
+          .SetExtension(
+            TestMessageSetExtension2.Types.MessageSetExtension,
+            TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
+          .SetUnknownFields(
+            UnknownFieldSet.CreateBuilder()
+              .AddField(UnknownTypeId,
+                UnknownField.CreateBuilder()
+                  .AddLengthDelimited(ByteString.CopyFromUtf8("bar"))
+                  .Build())
+              .Build())
+          .Build();
+
+      ByteString data = messageSet.ToByteString();
+
+      // Parse back using RawMessageSet and check the contents.
+      RawMessageSet raw = RawMessageSet.ParseFrom(data);
+
+      Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
+
+      Assert.AreEqual(3, raw.ItemCount);
+      Assert.AreEqual(TypeId1, raw.ItemList[0].TypeId);
+      Assert.AreEqual(TypeId2, raw.ItemList[1].TypeId);
+      Assert.AreEqual(UnknownTypeId, raw.ItemList[2].TypeId);
+
+      TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
+      Assert.AreEqual(123, message1.I);
+
+      TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
+      Assert.AreEqual("foo", message2.Str);
+
+      Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
+    }
+     
+    [Test]
+    public void ParseMessageSet() {
+      ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
+      extensionRegistry.Add(TestMessageSetExtension1.Types.MessageSetExtension);
+      extensionRegistry.Add(TestMessageSetExtension2.Types.MessageSetExtension);
+
+      // Set up a RawMessageSet with two known messages and an unknown one.
+      RawMessageSet raw =
+        RawMessageSet.CreateBuilder()
+          .AddItem(
+            RawMessageSet.Types.Item.CreateBuilder()
+              .SetTypeId(TypeId1)
+              .SetMessage(
+                TestMessageSetExtension1.CreateBuilder()
+                  .SetI(123)
+                  .Build().ToByteString())
+              .Build())
+          .AddItem(
+            RawMessageSet.Types.Item.CreateBuilder()
+              .SetTypeId(TypeId2)
+              .SetMessage(
+                TestMessageSetExtension2.CreateBuilder()
+                  .SetStr("foo")
+                  .Build().ToByteString())
+              .Build())
+          .AddItem(
+            RawMessageSet.Types.Item.CreateBuilder()
+              .SetTypeId(UnknownTypeId)
+              .SetMessage(ByteString.CopyFromUtf8("bar"))
+              .Build())
+          .Build();
+
+      ByteString data = raw.ToByteString();
+
+      // Parse as a TestMessageSet and check the contents.
+      TestMessageSet messageSet =
+        TestMessageSet.ParseFrom(data, extensionRegistry);
+
+      Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.Types.MessageSetExtension).I);
+      Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.Types.MessageSetExtension).Str);
+
+      // Check for unknown field with type LENGTH_DELIMITED,
+      //   number UNKNOWN_TYPE_ID, and contents "bar".
+      UnknownFieldSet unknownFields = messageSet.UnknownFields;
+      Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
+      Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
+
+      UnknownField field = unknownFields[UnknownTypeId];
+      Assert.AreEqual(1, field.LengthDelimitedList.Count);
+      Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
+    }
+
   }
 }

+ 1 - 1
csharp/ProtocolBuffers/DynamicMessage.cs

@@ -233,7 +233,7 @@ namespace Google.ProtocolBuffers {
 
       internal Builder(MessageDescriptor type) {
         this.type = type;
-        this.fields = FieldSet.CreateFieldSet();
+        this.fields = FieldSet.CreateInstance();
         this.unknownFields = UnknownFieldSet.DefaultInstance;
       }
 

+ 1 - 1
csharp/ProtocolBuffers/ExtendableMessage.cs

@@ -10,7 +10,7 @@ namespace Google.ProtocolBuffers {
     where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
 
     protected ExtendableMessage() {}
-    private readonly FieldSet extensions = FieldSet.CreateFieldSet();
+    private readonly FieldSet extensions = FieldSet.CreateInstance();
 
     /// <summary>
     /// Access for the builder.

+ 4 - 3
csharp/ProtocolBuffers/FieldSet.cs

@@ -30,8 +30,9 @@ namespace Google.ProtocolBuffers {
       this.fields = fields;
     }
 
-    public static FieldSet CreateFieldSet() {
-      return new FieldSet(new Dictionary<FieldDescriptor, object>());
+    public static FieldSet CreateInstance() {
+      // Use SortedList to keep fields in the canonical order
+      return new FieldSet(new SortedList<FieldDescriptor, object>());
     }
 
     /// <summary>
@@ -507,7 +508,7 @@ namespace Google.ProtocolBuffers {
     }
 
     /// <summary>
-    /// See <see cref="IBuilder.MergeFrom(IMessage)" />
+    /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessage)" />
     /// </summary>
     public void MergeFrom(IMessage other) {
       MergeFields(other.AllFields);

+ 12 - 12
csharp/ProtocolBuffers/IBuilder.cs

@@ -35,6 +35,18 @@ namespace Google.ProtocolBuffers {
     /// </summary>
     bool IsInitialized { get; }
 
+    /// <summary>
+    /// Only present in the nongeneric interface - useful for tests, but
+    /// not as much in real life.
+    /// </summary>
+    IBuilder SetField(FieldDescriptor field, object value);
+
+    /// <summary>
+    /// Only present in the nongeneric interface - useful for tests, but
+    /// not as much in real life.
+    /// </summary>
+    IBuilder SetRepeatedField(FieldDescriptor field, int index, object value);
+
     /// <summary>
     /// Behaves like the equivalent property in IMessage&lt;T&gt;.
     /// The returned map may or may not reflect future changes to the builder.
@@ -56,18 +68,6 @@ namespace Google.ProtocolBuffers {
     /// </summary>
     MessageDescriptor DescriptorForType { get; }
 
-    /// <summary>
-    /// Only present in the nongeneric interface - useful for tests, but
-    /// not as much in real life.
-    /// </summary>
-    IBuilder SetField(FieldDescriptor field, object value);
-
-    /// <summary>
-    /// Only present in the nongeneric interface - useful for tests, but
-    /// not as much in real life.
-    /// </summary>
-    IBuilder SetRepeatedField(FieldDescriptor field, int index, object value);
-
     /// <summary>
     /// <see cref="IMessage{TMessage, TBuilder}.GetRepeatedFieldCount"/>
     /// </summary>

+ 1 - 1
csharp/ProtocolBuffers/RpcUtil.cs

@@ -26,7 +26,7 @@ namespace Google.ProtocolBuffers {
         where TBuilder : IBuilder<TMessage, TBuilder> {
       return message => {
         TMessage castMessage = message as TMessage;
-        if (castMessage == null) {
+        if (castMessage == null) {  
           castMessage = defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
         }
         action(castMessage);

+ 1 - 0
java/src/test/java/com/google/protobuf/WireFormatTest.java

@@ -91,6 +91,7 @@ public class WireFormatTest extends TestCase {
       }
 
       assertTrue(tag > previousTag);
+      previousTag = tag;
       input.skipField(tag);
     }
   }