blob: e61f4cca97dcbf1d51eb23387e7204c02c90ceaa [file] [log] [blame]
Jon Skeet0aac0e42009-09-09 18:48:02 +01001#region Copyright notice and license
Jon Skeet60c059b2008-10-23 21:17:56 +01002// Protocol Buffers - Google's data interchange format
3// Copyright 2008 Google Inc. All rights reserved.
4// http://github.com/jskeet/dotnet-protobufs/
5// Original C++/Java/Python code:
Jon Skeet68036862008-10-22 13:30:34 +01006// http://code.google.com/p/protobuf/
7//
Jon Skeet60c059b2008-10-23 21:17:56 +01008// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
Jon Skeet68036862008-10-22 13:30:34 +010011//
Jon Skeet60c059b2008-10-23 21:17:56 +010012// * Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14// * Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following disclaimer
16// in the documentation and/or other materials provided with the
17// distribution.
18// * Neither the name of Google Inc. nor the names of its
19// contributors may be used to endorse or promote products derived from
20// this software without specific prior written permission.
Jon Skeet68036862008-10-22 13:30:34 +010021//
Jon Skeet60c059b2008-10-23 21:17:56 +010022// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Jon Skeet0aac0e42009-09-09 18:48:02 +010033#endregion
34
Jon Skeet2e6dc122009-05-29 06:34:52 +010035using System.IO;
Jon Skeet68036862008-10-22 13:30:34 +010036using System.Reflection;
37using Google.ProtocolBuffers.Descriptors;
38using Google.ProtocolBuffers.TestProtos;
39using NUnit.Framework;
40
41namespace Google.ProtocolBuffers {
42 [TestFixture]
43 public class WireFormatTest {
44
45 /// <summary>
46 /// Keeps the attributes on FieldType and the switch statement in WireFormat in sync.
47 /// </summary>
48 [Test]
49 public void FieldTypeToWireTypeMapping() {
50 foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
51 FieldType fieldType = (FieldType)field.GetValue(null);
52 FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
53 Assert.AreEqual(mapping.WireType, WireFormat.GetWireType(fieldType));
54 }
55 }
56
57 [Test]
58 public void Serialization() {
59 TestAllTypes message = TestUtil.GetAllSet();
60
61 ByteString rawBytes = message.ToByteString();
62 Assert.AreEqual(rawBytes.Length, message.SerializedSize);
63
64 TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
65
66 TestUtil.AssertAllFieldsSet(message2);
67 }
68
69 [Test]
Jon Skeet25a28582009-02-18 16:06:22 +000070 public void SerializationPacked() {
71 TestPackedTypes message = TestUtil.GetPackedSet();
72 ByteString rawBytes = message.ToByteString();
73 Assert.AreEqual(rawBytes.Length, message.SerializedSize);
74 TestPackedTypes message2 = TestPackedTypes.ParseFrom(rawBytes);
75 TestUtil.AssertPackedFieldsSet(message2);
76 }
77
78 [Test]
Jon Skeet68036862008-10-22 13:30:34 +010079 public void SerializeExtensions() {
80 // TestAllTypes and TestAllExtensions should have compatible wire formats,
Jon Skeet25a28582009-02-18 16:06:22 +000081 // so if we serialize a TestAllExtensions then parse it as TestAllTypes
Jon Skeet68036862008-10-22 13:30:34 +010082 // it should work.
Jon Skeet68036862008-10-22 13:30:34 +010083 TestAllExtensions message = TestUtil.GetAllExtensionsSet();
84 ByteString rawBytes = message.ToByteString();
85 Assert.AreEqual(rawBytes.Length, message.SerializedSize);
86
87 TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
88
89 TestUtil.AssertAllFieldsSet(message2);
90 }
91
92 [Test]
Jon Skeet25a28582009-02-18 16:06:22 +000093 public void SerializePackedExtensions() {
94 // TestPackedTypes and TestPackedExtensions should have compatible wire
95 // formats; check that they serialize to the same string.
96 TestPackedExtensions message = TestUtil.GetPackedExtensionsSet();
97 ByteString rawBytes = message.ToByteString();
98
99 TestPackedTypes message2 = TestUtil.GetPackedSet();
100 ByteString rawBytes2 = message2.ToByteString();
101
102 Assert.AreEqual(rawBytes, rawBytes2);
103 }
104
105 [Test]
Jon Skeet2e6dc122009-05-29 06:34:52 +0100106 public void SerializeDelimited() {
107 MemoryStream stream = new MemoryStream();
108 TestUtil.GetAllSet().WriteDelimitedTo(stream);
109 stream.WriteByte(12);
110 TestUtil.GetPackedSet().WriteDelimitedTo(stream);
111 stream.WriteByte(34);
112
113 stream.Position = 0;
114
115 TestUtil.AssertAllFieldsSet(TestAllTypes.ParseDelimitedFrom(stream));
116 Assert.AreEqual(12, stream.ReadByte());
117 TestUtil.AssertPackedFieldsSet(TestPackedTypes.ParseDelimitedFrom(stream));
118 Assert.AreEqual(34, stream.ReadByte());
119 Assert.AreEqual(-1, stream.ReadByte());
120 }
121
122 [Test]
Jon Skeet68036862008-10-22 13:30:34 +0100123 public void ParseExtensions() {
124 // TestAllTypes and TestAllExtensions should have compatible wire formats,
125 // so if we serealize a TestAllTypes then parse it as TestAllExtensions
126 // it should work.
127
128 TestAllTypes message = TestUtil.GetAllSet();
129 ByteString rawBytes = message.ToByteString();
130
131 ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
132 TestUtil.RegisterAllExtensions(registry);
133 registry = registry.AsReadOnly();
134
Jon Skeet25a28582009-02-18 16:06:22 +0000135 TestAllExtensions message2 = TestAllExtensions.ParseFrom(rawBytes, registry);
Jon Skeet68036862008-10-22 13:30:34 +0100136
137 TestUtil.AssertAllExtensionsSet(message2);
138 }
139
140 [Test]
Jon Skeet25a28582009-02-18 16:06:22 +0000141 public void ParsePackedExtensions() {
142 // Ensure that packed extensions can be properly parsed.
143 TestPackedExtensions message = TestUtil.GetPackedExtensionsSet();
144 ByteString rawBytes = message.ToByteString();
145
146 ExtensionRegistry registry = TestUtil.CreateExtensionRegistry();
147
148 TestPackedExtensions message2 = TestPackedExtensions.ParseFrom(rawBytes, registry);
149 TestUtil.AssertPackedExtensionsSet(message2);
150 }
151
152 [Test]
Jon Skeet68036862008-10-22 13:30:34 +0100153 public void ExtensionsSerializedSize() {
154 Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize);
155 }
156
Jon Skeet2e6dc122009-05-29 06:34:52 +0100157 private static void AssertFieldsInOrder(ByteString data) {
Jon Skeet68036862008-10-22 13:30:34 +0100158 CodedInputStream input = data.CreateCodedInput();
159 uint previousTag = 0;
160
161 while (true) {
162 uint tag = input.ReadTag();
163 if (tag == 0) {
164 break;
165 }
166
167 Assert.IsTrue(tag > previousTag);
168 previousTag = tag;
169 input.SkipField(tag);
170 }
171 }
172
173 [Test]
174 public void InterleavedFieldsAndExtensions() {
175 // Tests that fields are written in order even when extension ranges
176 // are interleaved with field numbers.
177 ByteString data =
178 TestFieldOrderings.CreateBuilder()
179 .SetMyInt(1)
180 .SetMyString("foo")
181 .SetMyFloat(1.0F)
182 .SetExtension(UnitTestProtoFile.MyExtensionInt, 23)
183 .SetExtension(UnitTestProtoFile.MyExtensionString, "bar")
184 .Build().ToByteString();
185 AssertFieldsInOrder(data);
186
187 MessageDescriptor descriptor = TestFieldOrderings.Descriptor;
188 ByteString dynamic_data =
189 DynamicMessage.CreateBuilder(TestFieldOrderings.Descriptor)
190 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_int"), 1L)
191 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_string"), "foo")
192 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_float"), 1.0F)
193 .SetField(UnitTestProtoFile.MyExtensionInt.Descriptor, 23)
194 .SetField(UnitTestProtoFile.MyExtensionString.Descriptor, "bar")
195 .WeakBuild().ToByteString();
196 AssertFieldsInOrder(dynamic_data);
197 }
198
199 private const int UnknownTypeId = 1550055;
200 private static readonly int TypeId1 = TestMessageSetExtension1.Descriptor.Extensions[0].FieldNumber;
201 private static readonly int TypeId2 = TestMessageSetExtension2.Descriptor.Extensions[0].FieldNumber;
202
203 [Test]
204 public void SerializeMessageSet() {
205 // Set up a TestMessageSet with two known messages and an unknown one.
206 TestMessageSet messageSet =
207 TestMessageSet.CreateBuilder()
208 .SetExtension(
209 TestMessageSetExtension1.MessageSetExtension,
210 TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
211 .SetExtension(
212 TestMessageSetExtension2.MessageSetExtension,
213 TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
214 .SetUnknownFields(
215 UnknownFieldSet.CreateBuilder()
216 .AddField(UnknownTypeId,
217 UnknownField.CreateBuilder()
218 .AddLengthDelimited(ByteString.CopyFromUtf8("bar"))
219 .Build())
220 .Build())
221 .Build();
222
223 ByteString data = messageSet.ToByteString();
224
225 // Parse back using RawMessageSet and check the contents.
226 RawMessageSet raw = RawMessageSet.ParseFrom(data);
227
228 Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
229
230 Assert.AreEqual(3, raw.ItemCount);
231 Assert.AreEqual(TypeId1, raw.ItemList[0].TypeId);
232 Assert.AreEqual(TypeId2, raw.ItemList[1].TypeId);
233 Assert.AreEqual(UnknownTypeId, raw.ItemList[2].TypeId);
234
235 TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
236 Assert.AreEqual(123, message1.I);
237
238 TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
239 Assert.AreEqual("foo", message2.Str);
240
241 Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
242 }
243
244 [Test]
245 public void ParseMessageSet() {
246 ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
247 extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
248 extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
249
250 // Set up a RawMessageSet with two known messages and an unknown one.
251 RawMessageSet raw =
252 RawMessageSet.CreateBuilder()
253 .AddItem(
254 RawMessageSet.Types.Item.CreateBuilder()
255 .SetTypeId(TypeId1)
256 .SetMessage(
257 TestMessageSetExtension1.CreateBuilder()
258 .SetI(123)
259 .Build().ToByteString())
260 .Build())
261 .AddItem(
262 RawMessageSet.Types.Item.CreateBuilder()
263 .SetTypeId(TypeId2)
264 .SetMessage(
265 TestMessageSetExtension2.CreateBuilder()
266 .SetStr("foo")
267 .Build().ToByteString())
268 .Build())
269 .AddItem(
270 RawMessageSet.Types.Item.CreateBuilder()
271 .SetTypeId(UnknownTypeId)
272 .SetMessage(ByteString.CopyFromUtf8("bar"))
273 .Build())
274 .Build();
275
276 ByteString data = raw.ToByteString();
277
278 // Parse as a TestMessageSet and check the contents.
279 TestMessageSet messageSet =
280 TestMessageSet.ParseFrom(data, extensionRegistry);
281
282 Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
283 Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
284
285 // Check for unknown field with type LENGTH_DELIMITED,
286 // number UNKNOWN_TYPE_ID, and contents "bar".
287 UnknownFieldSet unknownFields = messageSet.UnknownFields;
288 Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
289 Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
290
291 UnknownField field = unknownFields[UnknownTypeId];
292 Assert.AreEqual(1, field.LengthDelimitedList.Count);
293 Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
294 }
295
296 }
297}