blob: 891cf357d866a6463376f3137bc58f8a415b5567 [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]
66 public void SerializeExtensions() {
67 // TestAllTypes and TestAllExtensions should have compatible wire formats,
68 // so if we serealize a TestAllExtensions then parse it as TestAllTypes
69 // it should work.
70
71 TestAllExtensions message = TestUtil.GetAllExtensionsSet();
72 ByteString rawBytes = message.ToByteString();
73 Assert.AreEqual(rawBytes.Length, message.SerializedSize);
74
75 TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
76
77 TestUtil.AssertAllFieldsSet(message2);
78 }
79
80 [Test]
81 public void ParseExtensions() {
82 // TestAllTypes and TestAllExtensions should have compatible wire formats,
83 // so if we serealize a TestAllTypes then parse it as TestAllExtensions
84 // it should work.
85
86 TestAllTypes message = TestUtil.GetAllSet();
87 ByteString rawBytes = message.ToByteString();
88
89 ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
90 TestUtil.RegisterAllExtensions(registry);
91 registry = registry.AsReadOnly();
92
93 TestAllExtensions message2 =
94 TestAllExtensions.ParseFrom(rawBytes, registry);
95
96 TestUtil.AssertAllExtensionsSet(message2);
97 }
98
99 [Test]
100 public void ExtensionsSerializedSize() {
101 Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize);
102 }
103
104 private void AssertFieldsInOrder(ByteString data) {
105 CodedInputStream input = data.CreateCodedInput();
106 uint previousTag = 0;
107
108 while (true) {
109 uint tag = input.ReadTag();
110 if (tag == 0) {
111 break;
112 }
113
114 Assert.IsTrue(tag > previousTag);
115 previousTag = tag;
116 input.SkipField(tag);
117 }
118 }
119
120 [Test]
121 public void InterleavedFieldsAndExtensions() {
122 // Tests that fields are written in order even when extension ranges
123 // are interleaved with field numbers.
124 ByteString data =
125 TestFieldOrderings.CreateBuilder()
126 .SetMyInt(1)
127 .SetMyString("foo")
128 .SetMyFloat(1.0F)
129 .SetExtension(UnitTestProtoFile.MyExtensionInt, 23)
130 .SetExtension(UnitTestProtoFile.MyExtensionString, "bar")
131 .Build().ToByteString();
132 AssertFieldsInOrder(data);
133
134 MessageDescriptor descriptor = TestFieldOrderings.Descriptor;
135 ByteString dynamic_data =
136 DynamicMessage.CreateBuilder(TestFieldOrderings.Descriptor)
137 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_int"), 1L)
138 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_string"), "foo")
139 .SetField(descriptor.FindDescriptor<FieldDescriptor>("my_float"), 1.0F)
140 .SetField(UnitTestProtoFile.MyExtensionInt.Descriptor, 23)
141 .SetField(UnitTestProtoFile.MyExtensionString.Descriptor, "bar")
142 .WeakBuild().ToByteString();
143 AssertFieldsInOrder(dynamic_data);
144 }
145
146 private const int UnknownTypeId = 1550055;
147 private static readonly int TypeId1 = TestMessageSetExtension1.Descriptor.Extensions[0].FieldNumber;
148 private static readonly int TypeId2 = TestMessageSetExtension2.Descriptor.Extensions[0].FieldNumber;
149
150 [Test]
151 public void SerializeMessageSet() {
152 // Set up a TestMessageSet with two known messages and an unknown one.
153 TestMessageSet messageSet =
154 TestMessageSet.CreateBuilder()
155 .SetExtension(
156 TestMessageSetExtension1.MessageSetExtension,
157 TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
158 .SetExtension(
159 TestMessageSetExtension2.MessageSetExtension,
160 TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
161 .SetUnknownFields(
162 UnknownFieldSet.CreateBuilder()
163 .AddField(UnknownTypeId,
164 UnknownField.CreateBuilder()
165 .AddLengthDelimited(ByteString.CopyFromUtf8("bar"))
166 .Build())
167 .Build())
168 .Build();
169
170 ByteString data = messageSet.ToByteString();
171
172 // Parse back using RawMessageSet and check the contents.
173 RawMessageSet raw = RawMessageSet.ParseFrom(data);
174
175 Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
176
177 Assert.AreEqual(3, raw.ItemCount);
178 Assert.AreEqual(TypeId1, raw.ItemList[0].TypeId);
179 Assert.AreEqual(TypeId2, raw.ItemList[1].TypeId);
180 Assert.AreEqual(UnknownTypeId, raw.ItemList[2].TypeId);
181
182 TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
183 Assert.AreEqual(123, message1.I);
184
185 TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
186 Assert.AreEqual("foo", message2.Str);
187
188 Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
189 }
190
191 [Test]
192 public void ParseMessageSet() {
193 ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
194 extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
195 extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
196
197 // Set up a RawMessageSet with two known messages and an unknown one.
198 RawMessageSet raw =
199 RawMessageSet.CreateBuilder()
200 .AddItem(
201 RawMessageSet.Types.Item.CreateBuilder()
202 .SetTypeId(TypeId1)
203 .SetMessage(
204 TestMessageSetExtension1.CreateBuilder()
205 .SetI(123)
206 .Build().ToByteString())
207 .Build())
208 .AddItem(
209 RawMessageSet.Types.Item.CreateBuilder()
210 .SetTypeId(TypeId2)
211 .SetMessage(
212 TestMessageSetExtension2.CreateBuilder()
213 .SetStr("foo")
214 .Build().ToByteString())
215 .Build())
216 .AddItem(
217 RawMessageSet.Types.Item.CreateBuilder()
218 .SetTypeId(UnknownTypeId)
219 .SetMessage(ByteString.CopyFromUtf8("bar"))
220 .Build())
221 .Build();
222
223 ByteString data = raw.ToByteString();
224
225 // Parse as a TestMessageSet and check the contents.
226 TestMessageSet messageSet =
227 TestMessageSet.ParseFrom(data, extensionRegistry);
228
229 Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
230 Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
231
232 // Check for unknown field with type LENGTH_DELIMITED,
233 // number UNKNOWN_TYPE_ID, and contents "bar".
234 UnknownFieldSet unknownFields = messageSet.UnknownFields;
235 Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
236 Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
237
238 UnknownField field = unknownFields[UnknownTypeId];
239 Assert.AreEqual(1, field.LengthDelimitedList.Count);
240 Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
241 }
242
243 }
244}