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