blob: e390ce0d224ac081275a7f1fbf826004268f3bd3 [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
csharptest123e5342011-06-03 14:15:21 -0500176 uint tag;
177 string name;
178 while (input.ReadTag(out tag, out name))
csharptest71f662c2011-05-20 15:15:34 -0500179 {
csharptest71f662c2011-05-20 15:15:34 -0500180 Assert.IsTrue(tag > previousTag);
181 previousTag = tag;
csharptest123e5342011-06-03 14:15:21 -0500182 input.SkipField();
csharptest71f662c2011-05-20 15:15:34 -0500183 }
184 }
185
186 [Test]
187 public void InterleavedFieldsAndExtensions()
188 {
189 // Tests that fields are written in order even when extension ranges
190 // are interleaved with field numbers.
191 ByteString data =
192 TestFieldOrderings.CreateBuilder()
193 .SetMyInt(1)
194 .SetMyString("foo")
195 .SetMyFloat(1.0F)
196 .SetExtension(UnitTestProtoFile.MyExtensionInt, 23)
197 .SetExtension(UnitTestProtoFile.MyExtensionString, "bar")
198 .Build().ToByteString();
199 AssertFieldsInOrder(data);
200
201 MessageDescriptor descriptor = TestFieldOrderings.Descriptor;
202 ByteString dynamic_data =
203 DynamicMessage.CreateBuilder(TestFieldOrderings.Descriptor)
204 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_int"), 1L)
205 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_string"), "foo")
206 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_float"), 1.0F)
207 .SetField(UnitTestProtoFile.MyExtensionInt.Descriptor, 23)
208 .SetField(UnitTestProtoFile.MyExtensionString.Descriptor, "bar")
209 .WeakBuild().ToByteString();
210 AssertFieldsInOrder(dynamic_data);
211 }
212
213 private const int UnknownTypeId = 1550055;
214 private static readonly int TypeId1 = TestMessageSetExtension1.Descriptor.Extensions[0].FieldNumber;
215 private static readonly int TypeId2 = TestMessageSetExtension2.Descriptor.Extensions[0].FieldNumber;
216
217 [Test]
218 public void SerializeMessageSet()
219 {
220 // Set up a TestMessageSet with two known messages and an unknown one.
221 TestMessageSet messageSet =
222 TestMessageSet.CreateBuilder()
223 .SetExtension(
224 TestMessageSetExtension1.MessageSetExtension,
225 TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
226 .SetExtension(
227 TestMessageSetExtension2.MessageSetExtension,
228 TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
229 .SetUnknownFields(
230 UnknownFieldSet.CreateBuilder()
231 .AddField(UnknownTypeId,
232 UnknownField.CreateBuilder()
233 .AddLengthDelimited(ByteString.CopyFromUtf8("bar"))
234 .Build())
235 .Build())
236 .Build();
237
238 ByteString data = messageSet.ToByteString();
239
240 // Parse back using RawMessageSet and check the contents.
241 RawMessageSet raw = RawMessageSet.ParseFrom(data);
242
243 Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
244
245 Assert.AreEqual(3, raw.ItemCount);
246 Assert.AreEqual(TypeId1, raw.ItemList[0].TypeId);
247 Assert.AreEqual(TypeId2, raw.ItemList[1].TypeId);
248 Assert.AreEqual(UnknownTypeId, raw.ItemList[2].TypeId);
249
250 TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
251 Assert.AreEqual(123, message1.I);
252
253 TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
254 Assert.AreEqual("foo", message2.Str);
255
256 Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
257 }
258
259 [Test]
260 public void ParseMessageSet()
261 {
262 ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
263 extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
264 extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
265
266 // Set up a RawMessageSet with two known messages and an unknown one.
267 RawMessageSet raw =
268 RawMessageSet.CreateBuilder()
269 .AddItem(
270 RawMessageSet.Types.Item.CreateBuilder()
271 .SetTypeId(TypeId1)
272 .SetMessage(
273 TestMessageSetExtension1.CreateBuilder()
274 .SetI(123)
275 .Build().ToByteString())
276 .Build())
277 .AddItem(
278 RawMessageSet.Types.Item.CreateBuilder()
279 .SetTypeId(TypeId2)
280 .SetMessage(
281 TestMessageSetExtension2.CreateBuilder()
282 .SetStr("foo")
283 .Build().ToByteString())
284 .Build())
285 .AddItem(
286 RawMessageSet.Types.Item.CreateBuilder()
287 .SetTypeId(UnknownTypeId)
288 .SetMessage(ByteString.CopyFromUtf8("bar"))
289 .Build())
290 .Build();
291
292 ByteString data = raw.ToByteString();
293
294 // Parse as a TestMessageSet and check the contents.
295 TestMessageSet messageSet =
296 TestMessageSet.ParseFrom(data, extensionRegistry);
297
298 Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
299 Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
300
301 // Check for unknown field with type LENGTH_DELIMITED,
302 // number UNKNOWN_TYPE_ID, and contents "bar".
303 UnknownFieldSet unknownFields = messageSet.UnknownFields;
304 Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
305 Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
306
307 UnknownField field = unknownFields[UnknownTypeId];
308 Assert.AreEqual(1, field.LengthDelimitedList.Count);
309 Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
310 }
311 }
312}