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