WireFormatTest.cs 13.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#region Copyright notice and license

// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://github.com/jskeet/dotnet-protobufs/
// Original C++/Java/Python code:
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#endregion

using System.IO;
using System.Reflection;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
41
using NUnit.Framework;
42 43 44 45 46 47 48 49

namespace Google.ProtocolBuffers
{
    public class WireFormatTest
    {
        /// <summary>
        /// Keeps the attributes on FieldType and the switch statement in WireFormat in sync.
        /// </summary>
50
        [Test]
51 52
        public void FieldTypeToWireTypeMapping()
        {
53
            foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public))
54 55 56
            {
                FieldType fieldType = (FieldType) field.GetValue(null);
                FieldMappingAttribute mapping =
57
                    (FieldMappingAttribute) field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
58
                Assert.AreEqual(mapping.WireType, WireFormat.GetWireType(fieldType));
59 60 61
            }
        }

62
        [Test]
63 64 65 66 67
        public void Serialization()
        {
            TestAllTypes message = TestUtil.GetAllSet();

            ByteString rawBytes = message.ToByteString();
68
            Assert.AreEqual(rawBytes.Length, message.SerializedSize);
69 70 71 72 73 74

            TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);

            TestUtil.AssertAllFieldsSet(message2);
        }

75
        [Test]
76 77 78 79
        public void SerializationPacked()
        {
            TestPackedTypes message = TestUtil.GetPackedSet();
            ByteString rawBytes = message.ToByteString();
80
            Assert.AreEqual(rawBytes.Length, message.SerializedSize);
81 82 83 84
            TestPackedTypes message2 = TestPackedTypes.ParseFrom(rawBytes);
            TestUtil.AssertPackedFieldsSet(message2);
        }

85
        [Test]
86 87 88 89 90 91 92
        public void SerializeExtensions()
        {
            // TestAllTypes and TestAllExtensions should have compatible wire formats,
            // so if we serialize a TestAllExtensions then parse it as TestAllTypes
            // it should work.
            TestAllExtensions message = TestUtil.GetAllExtensionsSet();
            ByteString rawBytes = message.ToByteString();
93
            Assert.AreEqual(rawBytes.Length, message.SerializedSize);
94 95 96 97 98 99

            TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);

            TestUtil.AssertAllFieldsSet(message2);
        }

100
        [Test]
101 102 103 104 105 106 107 108 109 110
        public void SerializePackedExtensions()
        {
            // TestPackedTypes and TestPackedExtensions should have compatible wire
            // formats; check that they serialize to the same string.
            TestPackedExtensions message = TestUtil.GetPackedExtensionsSet();
            ByteString rawBytes = message.ToByteString();

            TestPackedTypes message2 = TestUtil.GetPackedSet();
            ByteString rawBytes2 = message2.ToByteString();

111
            Assert.AreEqual(rawBytes, rawBytes2);
112 113
        }

114
        [Test]
115 116 117 118 119 120 121 122 123 124 125
        public void SerializeDelimited()
        {
            MemoryStream stream = new MemoryStream();
            TestUtil.GetAllSet().WriteDelimitedTo(stream);
            stream.WriteByte(12);
            TestUtil.GetPackedSet().WriteDelimitedTo(stream);
            stream.WriteByte(34);

            stream.Position = 0;

            TestUtil.AssertAllFieldsSet(TestAllTypes.ParseDelimitedFrom(stream));
126
            Assert.AreEqual(12, stream.ReadByte());
127
            TestUtil.AssertPackedFieldsSet(TestPackedTypes.ParseDelimitedFrom(stream));
128 129
            Assert.AreEqual(34, stream.ReadByte());
            Assert.AreEqual(-1, stream.ReadByte());
130 131
        }

132
        [Test]
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
        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);
        }

151
        [Test]
152 153 154 155 156 157 158 159 160 161 162 163
        public void ParsePackedExtensions()
        {
            // Ensure that packed extensions can be properly parsed.
            TestPackedExtensions message = TestUtil.GetPackedExtensionsSet();
            ByteString rawBytes = message.ToByteString();

            ExtensionRegistry registry = TestUtil.CreateExtensionRegistry();

            TestPackedExtensions message2 = TestPackedExtensions.ParseFrom(rawBytes, registry);
            TestUtil.AssertPackedExtensionsSet(message2);
        }

164
        [Test]
165 166
        public void ExtensionsSerializedSize()
        {
Jie Luo's avatar
Jie Luo committed
167
            Assert.IsTrue(TestUtil.GetAllSet().SerializedSize < TestUtil.GetAllExtensionsSet().SerializedSize);
168 169 170 171 172 173 174
        }

        private static void AssertFieldsInOrder(ByteString data)
        {
            CodedInputStream input = data.CreateCodedInput();
            uint previousTag = 0;

175 176 177
            uint tag;
            string name;
            while (input.ReadTag(out tag, out name))
178
            {
179
                Assert.IsTrue(tag > previousTag);
180
                previousTag = tag;
181
                input.SkipField();
182 183 184
            }
        }

185
        [Test]
186 187 188 189 190 191 192 193 194
        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)
195 196
                    .SetExtension(Unittest.MyExtensionInt, 23)
                    .SetExtension(Unittest.MyExtensionString, "bar")
197 198 199 200 201 202 203 204 205
                    .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)
206 207
                    .SetField(Unittest.MyExtensionInt.Descriptor, 23)
                    .SetField(Unittest.MyExtensionString.Descriptor, "bar")
208 209 210 211 212 213 214 215
                    .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;

216
        [Test]
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
        public void SerializeMessageSet()
        {
            // Set up a TestMessageSet with two known messages and an unknown one.
            TestMessageSet messageSet =
                TestMessageSet.CreateBuilder()
                    .SetExtension(
                        TestMessageSetExtension1.MessageSetExtension,
                        TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
                    .SetExtension(
                        TestMessageSetExtension2.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);

242
            Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
243

244 245 246 247
            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);
248 249

            TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
250
            Assert.AreEqual(123, message1.I);
251 252

            TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
253
            Assert.AreEqual("foo", message2.Str);
254

255
            Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
256 257
        }

258
        [Test]
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
        public void ParseMessageSet()
        {
            ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
            extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
            extensionRegistry.Add(TestMessageSetExtension2.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);

297 298
            Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
            Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
299 300 301 302

            // Check for unknown field with type LENGTH_DELIMITED,
            //   number UNKNOWN_TYPE_ID, and contents "bar".
            UnknownFieldSet unknownFields = messageSet.UnknownFields;
303 304
            Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
            Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
305 306

            UnknownField field = unknownFields[UnknownTypeId];
307 308
            Assert.AreEqual(1, field.LengthDelimitedList.Count);
            Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
309 310 311
        }
    }
}