1 | #region Copyright notice and license
|
---|
2 | // 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:
|
---|
6 | // http://code.google.com/p/protobuf/
|
---|
7 | //
|
---|
8 | // Redistribution and use in source and binary forms, with or without
|
---|
9 | // modification, are permitted provided that the following conditions are
|
---|
10 | // met:
|
---|
11 | //
|
---|
12 | // * 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.
|
---|
21 | //
|
---|
22 | // 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.
|
---|
33 | #endregion
|
---|
34 |
|
---|
35 | using System;
|
---|
36 | using System.Collections.Generic;
|
---|
37 | using Google.ProtocolBuffers.Descriptors;
|
---|
38 | using Google.ProtocolBuffers.TestProtos;
|
---|
39 | using NUnit.Framework;
|
---|
40 |
|
---|
41 | namespace Google.ProtocolBuffers {
|
---|
42 | [TestFixture]
|
---|
43 | public class UnknownFieldSetTest {
|
---|
44 |
|
---|
45 | private MessageDescriptor descriptor;
|
---|
46 | private TestAllTypes allFields;
|
---|
47 | private ByteString allFieldsData;
|
---|
48 |
|
---|
49 | /// <summary>
|
---|
50 | /// An empty message that has been parsed from allFieldsData. So, it has
|
---|
51 | /// unknown fields of every type.
|
---|
52 | /// </summary>
|
---|
53 | private TestEmptyMessage emptyMessage;
|
---|
54 | private UnknownFieldSet unknownFields;
|
---|
55 |
|
---|
56 | [SetUp]
|
---|
57 | public void SetUp() {
|
---|
58 | descriptor = TestAllTypes.Descriptor;
|
---|
59 | allFields = TestUtil.GetAllSet();
|
---|
60 | allFieldsData = allFields.ToByteString();
|
---|
61 | emptyMessage = TestEmptyMessage.ParseFrom(allFieldsData);
|
---|
62 | unknownFields = emptyMessage.UnknownFields;
|
---|
63 | }
|
---|
64 |
|
---|
65 | private UnknownField GetField(String name) {
|
---|
66 | FieldDescriptor field = descriptor.FindDescriptor<FieldDescriptor>(name);
|
---|
67 | Assert.IsNotNull(field);
|
---|
68 | return unknownFields.FieldDictionary[field.FieldNumber];
|
---|
69 | }
|
---|
70 |
|
---|
71 | /// <summary>
|
---|
72 | /// Constructs a protocol buffer which contains fields with all the same
|
---|
73 | /// numbers as allFieldsData except that each field is some other wire
|
---|
74 | /// type.
|
---|
75 | /// </summary>
|
---|
76 | private ByteString GetBizarroData() {
|
---|
77 | UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.CreateBuilder();
|
---|
78 |
|
---|
79 | UnknownField varintField = UnknownField.CreateBuilder().AddVarint(1).Build();
|
---|
80 | UnknownField fixed32Field = UnknownField.CreateBuilder().AddFixed32(1).Build();
|
---|
81 |
|
---|
82 | foreach (KeyValuePair<int, UnknownField> entry in unknownFields.FieldDictionary) {
|
---|
83 | if (entry.Value.VarintList.Count == 0) {
|
---|
84 | // Original field is not a varint, so use a varint.
|
---|
85 | bizarroFields.AddField(entry.Key, varintField);
|
---|
86 | } else {
|
---|
87 | // Original field *is* a varint, so use something else.
|
---|
88 | bizarroFields.AddField(entry.Key, fixed32Field);
|
---|
89 | }
|
---|
90 | }
|
---|
91 |
|
---|
92 | return bizarroFields.Build().ToByteString();
|
---|
93 | }
|
---|
94 |
|
---|
95 | // =================================================================
|
---|
96 |
|
---|
97 | [Test]
|
---|
98 | public void Varint() {
|
---|
99 | UnknownField field = GetField("optional_int32");
|
---|
100 | Assert.AreEqual(1, field.VarintList.Count);
|
---|
101 | Assert.AreEqual(allFields.OptionalInt32, (long) field.VarintList[0]);
|
---|
102 | }
|
---|
103 |
|
---|
104 | [Test]
|
---|
105 | public void Fixed32() {
|
---|
106 | UnknownField field = GetField("optional_fixed32");
|
---|
107 | Assert.AreEqual(1, field.Fixed32List.Count);
|
---|
108 | Assert.AreEqual(allFields.OptionalFixed32, (int) field.Fixed32List[0]);
|
---|
109 | }
|
---|
110 |
|
---|
111 | [Test]
|
---|
112 | public void Fixed64() {
|
---|
113 | UnknownField field = GetField("optional_fixed64");
|
---|
114 | Assert.AreEqual(1, field.Fixed64List.Count);
|
---|
115 | Assert.AreEqual(allFields.OptionalFixed64, (long) field.Fixed64List[0]);
|
---|
116 | }
|
---|
117 |
|
---|
118 | [Test]
|
---|
119 | public void LengthDelimited() {
|
---|
120 | UnknownField field = GetField("optional_bytes");
|
---|
121 | Assert.AreEqual(1, field.LengthDelimitedList.Count);
|
---|
122 | Assert.AreEqual(allFields.OptionalBytes, field.LengthDelimitedList[0]);
|
---|
123 | }
|
---|
124 |
|
---|
125 | [Test]
|
---|
126 | public void Group() {
|
---|
127 | FieldDescriptor nestedFieldDescriptor =
|
---|
128 | TestAllTypes.Types.OptionalGroup.Descriptor.FindDescriptor<FieldDescriptor>("a");
|
---|
129 | Assert.IsNotNull(nestedFieldDescriptor);
|
---|
130 |
|
---|
131 | UnknownField field = GetField("optionalgroup");
|
---|
132 | Assert.AreEqual(1, field.GroupList.Count);
|
---|
133 |
|
---|
134 | UnknownFieldSet group = field.GroupList[0];
|
---|
135 | Assert.AreEqual(1, group.FieldDictionary.Count);
|
---|
136 | Assert.IsTrue(group.HasField(nestedFieldDescriptor.FieldNumber));
|
---|
137 |
|
---|
138 | UnknownField nestedField = group[nestedFieldDescriptor.FieldNumber];
|
---|
139 | Assert.AreEqual(1, nestedField.VarintList.Count);
|
---|
140 | Assert.AreEqual(allFields.OptionalGroup.A, (long) nestedField.VarintList[0]);
|
---|
141 | }
|
---|
142 |
|
---|
143 | [Test]
|
---|
144 | public void Serialize() {
|
---|
145 | // Check that serializing the UnknownFieldSet produces the original data again.
|
---|
146 | ByteString data = emptyMessage.ToByteString();
|
---|
147 | Assert.AreEqual(allFieldsData, data);
|
---|
148 | }
|
---|
149 |
|
---|
150 | [Test]
|
---|
151 | public void CopyFrom() {
|
---|
152 | TestEmptyMessage message =
|
---|
153 | TestEmptyMessage.CreateBuilder().MergeFrom(emptyMessage).Build();
|
---|
154 |
|
---|
155 | Assert.AreEqual(emptyMessage.ToString(), message.ToString());
|
---|
156 | }
|
---|
157 |
|
---|
158 | [Test]
|
---|
159 | public void MergeFrom() {
|
---|
160 | TestEmptyMessage source =
|
---|
161 | TestEmptyMessage.CreateBuilder()
|
---|
162 | .SetUnknownFields(
|
---|
163 | UnknownFieldSet.CreateBuilder()
|
---|
164 | .AddField(2,
|
---|
165 | UnknownField.CreateBuilder()
|
---|
166 | .AddVarint(2).Build())
|
---|
167 | .AddField(3,
|
---|
168 | UnknownField.CreateBuilder()
|
---|
169 | .AddVarint(4).Build())
|
---|
170 | .Build())
|
---|
171 | .Build();
|
---|
172 | TestEmptyMessage destination =
|
---|
173 | TestEmptyMessage.CreateBuilder()
|
---|
174 | .SetUnknownFields(
|
---|
175 | UnknownFieldSet.CreateBuilder()
|
---|
176 | .AddField(1,
|
---|
177 | UnknownField.CreateBuilder()
|
---|
178 | .AddVarint(1).Build())
|
---|
179 | .AddField(3,
|
---|
180 | UnknownField.CreateBuilder()
|
---|
181 | .AddVarint(3).Build())
|
---|
182 | .Build())
|
---|
183 | .MergeFrom(source)
|
---|
184 | .Build();
|
---|
185 |
|
---|
186 | Assert.AreEqual(
|
---|
187 | "1: 1\n" +
|
---|
188 | "2: 2\n" +
|
---|
189 | "3: 3\n" +
|
---|
190 | "3: 4\n",
|
---|
191 | destination.ToString());
|
---|
192 | }
|
---|
193 |
|
---|
194 | [Test]
|
---|
195 | public void Clear() {
|
---|
196 | UnknownFieldSet fields =
|
---|
197 | UnknownFieldSet.CreateBuilder().MergeFrom(unknownFields).Clear().Build();
|
---|
198 | Assert.AreEqual(0, fields.FieldDictionary.Count);
|
---|
199 | }
|
---|
200 |
|
---|
201 | [Test]
|
---|
202 | public void ClearMessage() {
|
---|
203 | TestEmptyMessage message =
|
---|
204 | TestEmptyMessage.CreateBuilder().MergeFrom(emptyMessage).Clear().Build();
|
---|
205 | Assert.AreEqual(0, message.SerializedSize);
|
---|
206 | }
|
---|
207 |
|
---|
208 | [Test]
|
---|
209 | public void ParseKnownAndUnknown() {
|
---|
210 | // Test mixing known and unknown fields when parsing.
|
---|
211 |
|
---|
212 | UnknownFieldSet fields =
|
---|
213 | UnknownFieldSet.CreateBuilder(unknownFields)
|
---|
214 | .AddField(123456,
|
---|
215 | UnknownField.CreateBuilder().AddVarint(654321).Build())
|
---|
216 | .Build();
|
---|
217 |
|
---|
218 | ByteString data = fields.ToByteString();
|
---|
219 | TestAllTypes destination = TestAllTypes.ParseFrom(data);
|
---|
220 |
|
---|
221 | TestUtil.AssertAllFieldsSet(destination);
|
---|
222 | Assert.AreEqual(1, destination.UnknownFields.FieldDictionary.Count);
|
---|
223 |
|
---|
224 | UnknownField field = destination.UnknownFields[123456];
|
---|
225 | Assert.AreEqual(1, field.VarintList.Count);
|
---|
226 | Assert.AreEqual(654321, (long) field.VarintList[0]);
|
---|
227 | }
|
---|
228 |
|
---|
229 | [Test]
|
---|
230 | public void WrongTypeTreatedAsUnknown() {
|
---|
231 | // Test that fields of the wrong wire type are treated like unknown fields
|
---|
232 | // when parsing.
|
---|
233 |
|
---|
234 | ByteString bizarroData = GetBizarroData();
|
---|
235 | TestAllTypes allTypesMessage = TestAllTypes.ParseFrom(bizarroData);
|
---|
236 | TestEmptyMessage emptyMessage = TestEmptyMessage.ParseFrom(bizarroData);
|
---|
237 |
|
---|
238 | // All fields should have been interpreted as unknown, so the debug strings
|
---|
239 | // should be the same.
|
---|
240 | Assert.AreEqual(emptyMessage.ToString(), allTypesMessage.ToString());
|
---|
241 | }
|
---|
242 |
|
---|
243 | [Test]
|
---|
244 | public void UnknownExtensions() {
|
---|
245 | // Make sure fields are properly parsed to the UnknownFieldSet even when
|
---|
246 | // they are declared as extension numbers.
|
---|
247 |
|
---|
248 | TestEmptyMessageWithExtensions message =
|
---|
249 | TestEmptyMessageWithExtensions.ParseFrom(allFieldsData);
|
---|
250 |
|
---|
251 | Assert.AreEqual(unknownFields.FieldDictionary.Count,
|
---|
252 | message.UnknownFields.FieldDictionary.Count);
|
---|
253 | Assert.AreEqual(allFieldsData, message.ToByteString());
|
---|
254 | }
|
---|
255 |
|
---|
256 | [Test]
|
---|
257 | public void WrongExtensionTypeTreatedAsUnknown() {
|
---|
258 | // Test that fields of the wrong wire type are treated like unknown fields
|
---|
259 | // when parsing extensions.
|
---|
260 |
|
---|
261 | ByteString bizarroData = GetBizarroData();
|
---|
262 | TestAllExtensions allExtensionsMessage = TestAllExtensions.ParseFrom(bizarroData);
|
---|
263 | TestEmptyMessage emptyMessage = TestEmptyMessage.ParseFrom(bizarroData);
|
---|
264 |
|
---|
265 | // All fields should have been interpreted as unknown, so the debug strings
|
---|
266 | // should be the same.
|
---|
267 | Assert.AreEqual(emptyMessage.ToString(),
|
---|
268 | allExtensionsMessage.ToString());
|
---|
269 | }
|
---|
270 |
|
---|
271 | [Test]
|
---|
272 | public void ParseUnknownEnumValue() {
|
---|
273 | FieldDescriptor singularField = TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("optional_nested_enum");
|
---|
274 | FieldDescriptor repeatedField = TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_nested_enum");
|
---|
275 | Assert.IsNotNull(singularField);
|
---|
276 | Assert.IsNotNull(repeatedField);
|
---|
277 |
|
---|
278 | ByteString data =
|
---|
279 | UnknownFieldSet.CreateBuilder()
|
---|
280 | .AddField(singularField.FieldNumber,
|
---|
281 | UnknownField.CreateBuilder()
|
---|
282 | .AddVarint((int) TestAllTypes.Types.NestedEnum.BAR)
|
---|
283 | .AddVarint(5) // not valid
|
---|
284 | .Build())
|
---|
285 | .AddField(repeatedField.FieldNumber,
|
---|
286 | UnknownField.CreateBuilder()
|
---|
287 | .AddVarint((int) TestAllTypes.Types.NestedEnum.FOO)
|
---|
288 | .AddVarint(4) // not valid
|
---|
289 | .AddVarint((int) TestAllTypes.Types.NestedEnum.BAZ)
|
---|
290 | .AddVarint(6) // not valid
|
---|
291 | .Build())
|
---|
292 | .Build()
|
---|
293 | .ToByteString();
|
---|
294 |
|
---|
295 | {
|
---|
296 | TestAllTypes message = TestAllTypes.ParseFrom(data);
|
---|
297 | Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR,
|
---|
298 | message.OptionalNestedEnum);
|
---|
299 | TestUtil.AssertEqual(new [] {TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.BAZ},
|
---|
300 | message.RepeatedNestedEnumList);
|
---|
301 | TestUtil.AssertEqual(new[] {5UL}, message.UnknownFields[singularField.FieldNumber].VarintList);
|
---|
302 | TestUtil.AssertEqual(new[] {4UL, 6UL}, message.UnknownFields[repeatedField.FieldNumber].VarintList);
|
---|
303 | }
|
---|
304 |
|
---|
305 | {
|
---|
306 | TestAllExtensions message =
|
---|
307 | TestAllExtensions.ParseFrom(data, TestUtil.CreateExtensionRegistry());
|
---|
308 | Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR,
|
---|
309 | message.GetExtension(UnitTestProtoFile.OptionalNestedEnumExtension));
|
---|
310 | TestUtil.AssertEqual(new[] { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.BAZ },
|
---|
311 | message.GetExtension(UnitTestProtoFile.RepeatedNestedEnumExtension));
|
---|
312 | TestUtil.AssertEqual(new[] { 5UL }, message.UnknownFields[singularField.FieldNumber].VarintList);
|
---|
313 | TestUtil.AssertEqual(new[] { 4UL, 6UL }, message.UnknownFields[repeatedField.FieldNumber].VarintList);
|
---|
314 | }
|
---|
315 | }
|
---|
316 |
|
---|
317 | [Test]
|
---|
318 | public void LargeVarint() {
|
---|
319 | ByteString data =
|
---|
320 | UnknownFieldSet.CreateBuilder()
|
---|
321 | .AddField(1,
|
---|
322 | UnknownField.CreateBuilder()
|
---|
323 | .AddVarint(0x7FFFFFFFFFFFFFFFL)
|
---|
324 | .Build())
|
---|
325 | .Build()
|
---|
326 | .ToByteString();
|
---|
327 | UnknownFieldSet parsed = UnknownFieldSet.ParseFrom(data);
|
---|
328 | UnknownField field = parsed[1];
|
---|
329 | Assert.AreEqual(1, field.VarintList.Count);
|
---|
330 | Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, field.VarintList[0]);
|
---|
331 | }
|
---|
332 |
|
---|
333 | [Test]
|
---|
334 | public void EqualsAndHashCode() {
|
---|
335 | UnknownField fixed32Field = UnknownField.CreateBuilder().AddFixed32(1).Build();
|
---|
336 | UnknownField fixed64Field = UnknownField.CreateBuilder().AddFixed64(1).Build();
|
---|
337 | UnknownField varIntField = UnknownField.CreateBuilder().AddVarint(1).Build();
|
---|
338 | UnknownField lengthDelimitedField = UnknownField.CreateBuilder().AddLengthDelimited(ByteString.Empty).Build();
|
---|
339 | UnknownField groupField = UnknownField.CreateBuilder().AddGroup(unknownFields).Build();
|
---|
340 |
|
---|
341 | UnknownFieldSet a = UnknownFieldSet.CreateBuilder().AddField(1, fixed32Field).Build();
|
---|
342 | UnknownFieldSet b = UnknownFieldSet.CreateBuilder().AddField(1, fixed64Field).Build();
|
---|
343 | UnknownFieldSet c = UnknownFieldSet.CreateBuilder().AddField(1, varIntField).Build();
|
---|
344 | UnknownFieldSet d = UnknownFieldSet.CreateBuilder().AddField(1, lengthDelimitedField).Build();
|
---|
345 | UnknownFieldSet e = UnknownFieldSet.CreateBuilder().AddField(1, groupField).Build();
|
---|
346 |
|
---|
347 | CheckEqualsIsConsistent(a);
|
---|
348 | CheckEqualsIsConsistent(b);
|
---|
349 | CheckEqualsIsConsistent(c);
|
---|
350 | CheckEqualsIsConsistent(d);
|
---|
351 | CheckEqualsIsConsistent(e);
|
---|
352 |
|
---|
353 | CheckNotEqual(a, b);
|
---|
354 | CheckNotEqual(a, c);
|
---|
355 | CheckNotEqual(a, d);
|
---|
356 | CheckNotEqual(a, e);
|
---|
357 | CheckNotEqual(b, c);
|
---|
358 | CheckNotEqual(b, d);
|
---|
359 | CheckNotEqual(b, e);
|
---|
360 | CheckNotEqual(c, d);
|
---|
361 | CheckNotEqual(c, e);
|
---|
362 | CheckNotEqual(d, e);
|
---|
363 | }
|
---|
364 |
|
---|
365 | /// <summary>
|
---|
366 | /// Asserts that the given field sets are not equal and have different
|
---|
367 | /// hash codes.
|
---|
368 | /// </summary>
|
---|
369 | /// <remarks>
|
---|
370 | /// It's valid for non-equal objects to have the same hash code, so
|
---|
371 | /// this test is stricter than it needs to be. However, this should happen
|
---|
372 | /// relatively rarely.
|
---|
373 | /// </remarks>
|
---|
374 | /// <param name="s1"></param>
|
---|
375 | /// <param name="s2"></param>
|
---|
376 | private static void CheckNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
|
---|
377 | String equalsError = string.Format("{0} should not be equal to {1}", s1, s2);
|
---|
378 | Assert.IsFalse(s1.Equals(s2), equalsError);
|
---|
379 | Assert.IsFalse(s2.Equals(s1), equalsError);
|
---|
380 |
|
---|
381 | Assert.IsFalse(s1.GetHashCode() == s2.GetHashCode(),
|
---|
382 | string.Format("{0} should have a different hash code from {1}", s1, s2));
|
---|
383 |
|
---|
384 | }
|
---|
385 |
|
---|
386 | /**
|
---|
387 | * Asserts that the given field sets are equal and have identical hash codes.
|
---|
388 | */
|
---|
389 | private static void CheckEqualsIsConsistent(UnknownFieldSet set) {
|
---|
390 | // Object should be equal to itself.
|
---|
391 | Assert.AreEqual(set, set);
|
---|
392 |
|
---|
393 | // Object should be equal to a copy of itself.
|
---|
394 | UnknownFieldSet copy = UnknownFieldSet.CreateBuilder(set).Build();
|
---|
395 | Assert.AreEqual(set, copy);
|
---|
396 | Assert.AreEqual(copy, set);
|
---|
397 | Assert.AreEqual(set.GetHashCode(), copy.GetHashCode());
|
---|
398 | }
|
---|
399 | }
|
---|
400 | }
|
---|