OLD | NEW |
| (Empty) |
1 #region Copyright notice and license | |
2 // Protocol Buffers - Google's data interchange format | |
3 // Copyright 2015 Google Inc. All rights reserved. | |
4 // https://developers.google.com/protocol-buffers/ | |
5 // | |
6 // Redistribution and use in source and binary forms, with or without | |
7 // modification, are permitted provided that the following conditions are | |
8 // met: | |
9 // | |
10 // * Redistributions of source code must retain the above copyright | |
11 // notice, this list of conditions and the following disclaimer. | |
12 // * Redistributions in binary form must reproduce the above | |
13 // copyright notice, this list of conditions and the following disclaimer | |
14 // in the documentation and/or other materials provided with the | |
15 // distribution. | |
16 // * Neither the name of Google Inc. nor the names of its | |
17 // contributors may be used to endorse or promote products derived from | |
18 // this software without specific prior written permission. | |
19 // | |
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 #endregion | |
32 | |
33 using System; | |
34 using System.IO; | |
35 using Google.Protobuf.TestProtos; | |
36 using NUnit.Framework; | |
37 using System.Collections; | |
38 using System.Collections.Generic; | |
39 using System.Linq; | |
40 using Google.Protobuf.WellKnownTypes; | |
41 | |
42 namespace Google.Protobuf | |
43 { | |
44 /// <summary> | |
45 /// Tests around the generated TestAllTypes message. | |
46 /// </summary> | |
47 public class GeneratedMessageTest | |
48 { | |
49 [Test] | |
50 public void EmptyMessageFieldDistinctFromMissingMessageField() | |
51 { | |
52 // This demonstrates what we're really interested in... | |
53 var message1 = new TestAllTypes { SingleForeignMessage = new Foreign
Message() }; | |
54 var message2 = new TestAllTypes(); // SingleForeignMessage is null | |
55 EqualityTester.AssertInequality(message1, message2); | |
56 } | |
57 | |
58 [Test] | |
59 public void DefaultValues() | |
60 { | |
61 // Single fields | |
62 var message = new TestAllTypes(); | |
63 Assert.AreEqual(false, message.SingleBool); | |
64 Assert.AreEqual(ByteString.Empty, message.SingleBytes); | |
65 Assert.AreEqual(0.0, message.SingleDouble); | |
66 Assert.AreEqual(0, message.SingleFixed32); | |
67 Assert.AreEqual(0L, message.SingleFixed64); | |
68 Assert.AreEqual(0.0f, message.SingleFloat); | |
69 Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForei
gnEnum); | |
70 Assert.IsNull(message.SingleForeignMessage); | |
71 Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleIm
portEnum); | |
72 Assert.IsNull(message.SingleImportMessage); | |
73 Assert.AreEqual(0, message.SingleInt32); | |
74 Assert.AreEqual(0L, message.SingleInt64); | |
75 Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIE
D, message.SingleNestedEnum); | |
76 Assert.IsNull(message.SingleNestedMessage); | |
77 Assert.IsNull(message.SinglePublicImportMessage); | |
78 Assert.AreEqual(0, message.SingleSfixed32); | |
79 Assert.AreEqual(0L, message.SingleSfixed64); | |
80 Assert.AreEqual(0, message.SingleSint32); | |
81 Assert.AreEqual(0L, message.SingleSint64); | |
82 Assert.AreEqual("", message.SingleString); | |
83 Assert.AreEqual(0U, message.SingleUint32); | |
84 Assert.AreEqual(0UL, message.SingleUint64); | |
85 | |
86 // Repeated fields | |
87 Assert.AreEqual(0, message.RepeatedBool.Count); | |
88 Assert.AreEqual(0, message.RepeatedBytes.Count); | |
89 Assert.AreEqual(0, message.RepeatedDouble.Count); | |
90 Assert.AreEqual(0, message.RepeatedFixed32.Count); | |
91 Assert.AreEqual(0, message.RepeatedFixed64.Count); | |
92 Assert.AreEqual(0, message.RepeatedFloat.Count); | |
93 Assert.AreEqual(0, message.RepeatedForeignEnum.Count); | |
94 Assert.AreEqual(0, message.RepeatedForeignMessage.Count); | |
95 Assert.AreEqual(0, message.RepeatedImportEnum.Count); | |
96 Assert.AreEqual(0, message.RepeatedImportMessage.Count); | |
97 Assert.AreEqual(0, message.RepeatedNestedEnum.Count); | |
98 Assert.AreEqual(0, message.RepeatedNestedMessage.Count); | |
99 Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count); | |
100 Assert.AreEqual(0, message.RepeatedSfixed32.Count); | |
101 Assert.AreEqual(0, message.RepeatedSfixed64.Count); | |
102 Assert.AreEqual(0, message.RepeatedSint32.Count); | |
103 Assert.AreEqual(0, message.RepeatedSint64.Count); | |
104 Assert.AreEqual(0, message.RepeatedString.Count); | |
105 Assert.AreEqual(0, message.RepeatedUint32.Count); | |
106 Assert.AreEqual(0, message.RepeatedUint64.Count); | |
107 | |
108 // Oneof fields | |
109 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.Oneof
FieldCase); | |
110 Assert.AreEqual(0, message.OneofUint32); | |
111 Assert.AreEqual("", message.OneofString); | |
112 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
113 Assert.IsNull(message.OneofNestedMessage); | |
114 } | |
115 | |
116 [Test] | |
117 public void NullStringAndBytesRejected() | |
118 { | |
119 var message = new TestAllTypes(); | |
120 Assert.Throws<ArgumentNullException>(() => message.SingleString = nu
ll); | |
121 Assert.Throws<ArgumentNullException>(() => message.OneofString = nul
l); | |
122 Assert.Throws<ArgumentNullException>(() => message.SingleBytes = nul
l); | |
123 Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null
); | |
124 } | |
125 | |
126 [Test] | |
127 public void RoundTrip_Empty() | |
128 { | |
129 var message = new TestAllTypes(); | |
130 // Without setting any values, there's nothing to write. | |
131 byte[] bytes = message.ToByteArray(); | |
132 Assert.AreEqual(0, bytes.Length); | |
133 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); | |
134 Assert.AreEqual(message, parsed); | |
135 } | |
136 | |
137 [Test] | |
138 public void RoundTrip_SingleValues() | |
139 { | |
140 var message = new TestAllTypes | |
141 { | |
142 SingleBool = true, | |
143 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4), | |
144 SingleDouble = 23.5, | |
145 SingleFixed32 = 23, | |
146 SingleFixed64 = 1234567890123, | |
147 SingleFloat = 12.25f, | |
148 SingleForeignEnum = ForeignEnum.FOREIGN_BAR, | |
149 SingleForeignMessage = new ForeignMessage { C = 10 }, | |
150 SingleImportEnum = ImportEnum.IMPORT_BAZ, | |
151 SingleImportMessage = new ImportMessage { D = 20 }, | |
152 SingleInt32 = 100, | |
153 SingleInt64 = 3210987654321, | |
154 SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO, | |
155 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb
= 35 }, | |
156 SinglePublicImportMessage = new PublicImportMessage { E = 54 }, | |
157 SingleSfixed32 = -123, | |
158 SingleSfixed64 = -12345678901234, | |
159 SingleSint32 = -456, | |
160 SingleSint64 = -12345678901235, | |
161 SingleString = "test", | |
162 SingleUint32 = uint.MaxValue, | |
163 SingleUint64 = ulong.MaxValue | |
164 }; | |
165 | |
166 byte[] bytes = message.ToByteArray(); | |
167 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); | |
168 Assert.AreEqual(message, parsed); | |
169 } | |
170 | |
171 [Test] | |
172 public void RoundTrip_RepeatedValues() | |
173 { | |
174 var message = new TestAllTypes | |
175 { | |
176 RepeatedBool = { true, false }, | |
177 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.Co
pyFrom(5, 6) }, | |
178 RepeatedDouble = { -12.25, 23.5 }, | |
179 RepeatedFixed32 = { uint.MaxValue, 23 }, | |
180 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 }, | |
181 RepeatedFloat = { 100f, 12.25f }, | |
182 RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOR
EIGN_BAR }, | |
183 RepeatedForeignMessage = { new ForeignMessage(), new ForeignMess
age { C = 10 } }, | |
184 RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_
ENUM_UNSPECIFIED }, | |
185 RepeatedImportMessage = { new ImportMessage { D = 20 }, new Impo
rtMessage { D = 25 } }, | |
186 RepeatedInt32 = { 100, 200 }, | |
187 RepeatedInt64 = { 3210987654321, long.MaxValue }, | |
188 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAl
lTypes.Types.NestedEnum.NEG }, | |
189 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage {
Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } }, | |
190 RepeatedPublicImportMessage = { new PublicImportMessage { E = 54
}, new PublicImportMessage { E = -1 } }, | |
191 RepeatedSfixed32 = { -123, 123 }, | |
192 RepeatedSfixed64 = { -12345678901234, 12345678901234 }, | |
193 RepeatedSint32 = { -456, 100 }, | |
194 RepeatedSint64 = { -12345678901235, 123 }, | |
195 RepeatedString = { "foo", "bar" }, | |
196 RepeatedUint32 = { uint.MaxValue, uint.MinValue }, | |
197 RepeatedUint64 = { ulong.MaxValue, uint.MinValue } | |
198 }; | |
199 | |
200 byte[] bytes = message.ToByteArray(); | |
201 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); | |
202 Assert.AreEqual(message, parsed); | |
203 } | |
204 | |
205 // Note that not every map within map_unittest_proto3 is used. They all
go through very | |
206 // similar code paths. The fact that all maps are present is validation
that we have codecs | |
207 // for every type. | |
208 [Test] | |
209 public void RoundTrip_Maps() | |
210 { | |
211 var message = new TestMap | |
212 { | |
213 MapBoolBool = { | |
214 { false, true }, | |
215 { true, false } | |
216 }, | |
217 MapInt32Bytes = { | |
218 { 5, ByteString.CopyFrom(6, 7, 8) }, | |
219 { 25, ByteString.CopyFrom(1, 2, 3, 4, 5) }, | |
220 { 10, ByteString.Empty } | |
221 }, | |
222 MapInt32ForeignMessage = { | |
223 { 0, new ForeignMessage { C = 10 } }, | |
224 { 5, null }, | |
225 }, | |
226 MapInt32Enum = { | |
227 { 1, MapEnum.MAP_ENUM_BAR }, | |
228 { 2000, MapEnum.MAP_ENUM_FOO } | |
229 } | |
230 }; | |
231 | |
232 byte[] bytes = message.ToByteArray(); | |
233 TestMap parsed = TestMap.Parser.ParseFrom(bytes); | |
234 Assert.AreEqual(message, parsed); | |
235 } | |
236 | |
237 [Test] | |
238 public void MapWithEmptyEntry() | |
239 { | |
240 var message = new TestMap | |
241 { | |
242 MapInt32Bytes = { { 0, ByteString.Empty } } | |
243 }; | |
244 | |
245 byte[] bytes = message.ToByteArray(); | |
246 Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), l
ength of entry (0; 1 byte) | |
247 | |
248 var parsed = TestMap.Parser.ParseFrom(bytes); | |
249 Assert.AreEqual(1, parsed.MapInt32Bytes.Count); | |
250 Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]); | |
251 } | |
252 | |
253 [Test] | |
254 public void MapWithOnlyValue() | |
255 { | |
256 // Hand-craft the stream to contain a single entry with just a value
. | |
257 var memoryStream = new MemoryStream(); | |
258 var output = new CodedOutputStream(memoryStream); | |
259 output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireForma
t.WireType.LengthDelimited); | |
260 var nestedMessage = new ForeignMessage { C = 20 }; | |
261 // Size of the entry (tag, size written by WriteMessage, data writte
n by WriteMessage) | |
262 output.WriteLength(2 + nestedMessage.CalculateSize()); | |
263 output.WriteTag(2, WireFormat.WireType.LengthDelimited); | |
264 output.WriteMessage(nestedMessage); | |
265 output.Flush(); | |
266 | |
267 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); | |
268 Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]); | |
269 } | |
270 | |
271 [Test] | |
272 public void MapIgnoresExtraFieldsWithinEntryMessages() | |
273 { | |
274 // Hand-craft the stream to contain a single entry with three fields | |
275 var memoryStream = new MemoryStream(); | |
276 var output = new CodedOutputStream(memoryStream); | |
277 | |
278 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
279 | |
280 var key = 10; // Field 1 | |
281 var value = 20; // Field 2 | |
282 var extra = 30; // Field 3 | |
283 | |
284 // Each field can be represented in a single byte, with a single byt
e tag. | |
285 // Total message size: 6 bytes. | |
286 output.WriteLength(6); | |
287 output.WriteTag(1, WireFormat.WireType.Varint); | |
288 output.WriteInt32(key); | |
289 output.WriteTag(2, WireFormat.WireType.Varint); | |
290 output.WriteInt32(value); | |
291 output.WriteTag(3, WireFormat.WireType.Varint); | |
292 output.WriteInt32(extra); | |
293 output.Flush(); | |
294 | |
295 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); | |
296 Assert.AreEqual(value, parsed.MapInt32Int32[key]); | |
297 } | |
298 | |
299 [Test] | |
300 public void MapFieldOrderIsIrrelevant() | |
301 { | |
302 var memoryStream = new MemoryStream(); | |
303 var output = new CodedOutputStream(memoryStream); | |
304 | |
305 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
306 | |
307 var key = 10; | |
308 var value = 20; | |
309 | |
310 // Each field can be represented in a single byte, with a single byt
e tag. | |
311 // Total message size: 4 bytes. | |
312 output.WriteLength(4); | |
313 output.WriteTag(2, WireFormat.WireType.Varint); | |
314 output.WriteInt32(value); | |
315 output.WriteTag(1, WireFormat.WireType.Varint); | |
316 output.WriteInt32(key); | |
317 output.Flush(); | |
318 | |
319 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); | |
320 Assert.AreEqual(value, parsed.MapInt32Int32[key]); | |
321 } | |
322 | |
323 [Test] | |
324 public void MapNonContiguousEntries() | |
325 { | |
326 var memoryStream = new MemoryStream(); | |
327 var output = new CodedOutputStream(memoryStream); | |
328 | |
329 // Message structure: | |
330 // Entry for MapInt32Int32 | |
331 // Entry for MapStringString | |
332 // Entry for MapInt32Int32 | |
333 | |
334 // First entry | |
335 var key1 = 10; | |
336 var value1 = 20; | |
337 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
338 output.WriteLength(4); | |
339 output.WriteTag(1, WireFormat.WireType.Varint); | |
340 output.WriteInt32(key1); | |
341 output.WriteTag(2, WireFormat.WireType.Varint); | |
342 output.WriteInt32(value1); | |
343 | |
344 // Second entry | |
345 var key2 = "a"; | |
346 var value2 = "b"; | |
347 output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireT
ype.LengthDelimited); | |
348 output.WriteLength(6); // 3 bytes per entry: tag, size, character | |
349 output.WriteTag(1, WireFormat.WireType.LengthDelimited); | |
350 output.WriteString(key2); | |
351 output.WriteTag(2, WireFormat.WireType.LengthDelimited); | |
352 output.WriteString(value2); | |
353 | |
354 // Third entry | |
355 var key3 = 15; | |
356 var value3 = 25; | |
357 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
358 output.WriteLength(4); | |
359 output.WriteTag(1, WireFormat.WireType.Varint); | |
360 output.WriteInt32(key3); | |
361 output.WriteTag(2, WireFormat.WireType.Varint); | |
362 output.WriteInt32(value3); | |
363 | |
364 output.Flush(); | |
365 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); | |
366 var expected = new TestMap | |
367 { | |
368 MapInt32Int32 = { { key1, value1 }, { key3, value3 } }, | |
369 MapStringString = { { key2, value2 } } | |
370 }; | |
371 Assert.AreEqual(expected, parsed); | |
372 } | |
373 | |
374 [Test] | |
375 public void DuplicateKeys_LastEntryWins() | |
376 { | |
377 var memoryStream = new MemoryStream(); | |
378 var output = new CodedOutputStream(memoryStream); | |
379 | |
380 var key = 10; | |
381 var value1 = 20; | |
382 var value2 = 30; | |
383 | |
384 // First entry | |
385 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
386 output.WriteLength(4); | |
387 output.WriteTag(1, WireFormat.WireType.Varint); | |
388 output.WriteInt32(key); | |
389 output.WriteTag(2, WireFormat.WireType.Varint); | |
390 output.WriteInt32(value1); | |
391 | |
392 // Second entry - same key, different value | |
393 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireTyp
e.LengthDelimited); | |
394 output.WriteLength(4); | |
395 output.WriteTag(1, WireFormat.WireType.Varint); | |
396 output.WriteInt32(key); | |
397 output.WriteTag(2, WireFormat.WireType.Varint); | |
398 output.WriteInt32(value2); | |
399 output.Flush(); | |
400 | |
401 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); | |
402 Assert.AreEqual(value2, parsed.MapInt32Int32[key]); | |
403 } | |
404 | |
405 [Test] | |
406 public void CloneSingleNonMessageValues() | |
407 { | |
408 var original = new TestAllTypes | |
409 { | |
410 SingleBool = true, | |
411 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4), | |
412 SingleDouble = 23.5, | |
413 SingleFixed32 = 23, | |
414 SingleFixed64 = 1234567890123, | |
415 SingleFloat = 12.25f, | |
416 SingleInt32 = 100, | |
417 SingleInt64 = 3210987654321, | |
418 SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO, | |
419 SingleSfixed32 = -123, | |
420 SingleSfixed64 = -12345678901234, | |
421 SingleSint32 = -456, | |
422 SingleSint64 = -12345678901235, | |
423 SingleString = "test", | |
424 SingleUint32 = uint.MaxValue, | |
425 SingleUint64 = ulong.MaxValue | |
426 }; | |
427 var clone = original.Clone(); | |
428 Assert.AreNotSame(original, clone); | |
429 Assert.AreEqual(original, clone); | |
430 // Just as a single example | |
431 clone.SingleInt32 = 150; | |
432 Assert.AreNotEqual(original, clone); | |
433 } | |
434 | |
435 [Test] | |
436 public void CloneRepeatedNonMessageValues() | |
437 { | |
438 var original = new TestAllTypes | |
439 { | |
440 RepeatedBool = { true, false }, | |
441 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.Co
pyFrom(5, 6) }, | |
442 RepeatedDouble = { -12.25, 23.5 }, | |
443 RepeatedFixed32 = { uint.MaxValue, 23 }, | |
444 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 }, | |
445 RepeatedFloat = { 100f, 12.25f }, | |
446 RepeatedInt32 = { 100, 200 }, | |
447 RepeatedInt64 = { 3210987654321, long.MaxValue }, | |
448 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAl
lTypes.Types.NestedEnum.NEG }, | |
449 RepeatedSfixed32 = { -123, 123 }, | |
450 RepeatedSfixed64 = { -12345678901234, 12345678901234 }, | |
451 RepeatedSint32 = { -456, 100 }, | |
452 RepeatedSint64 = { -12345678901235, 123 }, | |
453 RepeatedString = { "foo", "bar" }, | |
454 RepeatedUint32 = { uint.MaxValue, uint.MinValue }, | |
455 RepeatedUint64 = { ulong.MaxValue, uint.MinValue } | |
456 }; | |
457 | |
458 var clone = original.Clone(); | |
459 Assert.AreNotSame(original, clone); | |
460 Assert.AreEqual(original, clone); | |
461 // Just as a single example | |
462 clone.RepeatedDouble.Add(25.5); | |
463 Assert.AreNotEqual(original, clone); | |
464 } | |
465 | |
466 [Test] | |
467 public void CloneSingleMessageField() | |
468 { | |
469 var original = new TestAllTypes | |
470 { | |
471 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb
= 20 } | |
472 }; | |
473 | |
474 var clone = original.Clone(); | |
475 Assert.AreNotSame(original, clone); | |
476 Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMe
ssage); | |
477 Assert.AreEqual(original, clone); | |
478 | |
479 clone.SingleNestedMessage.Bb = 30; | |
480 Assert.AreNotEqual(original, clone); | |
481 } | |
482 | |
483 [Test] | |
484 public void CloneRepeatedMessageField() | |
485 { | |
486 var original = new TestAllTypes | |
487 { | |
488 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage {
Bb = 20 } } | |
489 }; | |
490 | |
491 var clone = original.Clone(); | |
492 Assert.AreNotSame(original, clone); | |
493 Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNest
edMessage); | |
494 Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedN
estedMessage[0]); | |
495 Assert.AreEqual(original, clone); | |
496 | |
497 clone.RepeatedNestedMessage[0].Bb = 30; | |
498 Assert.AreNotEqual(original, clone); | |
499 } | |
500 | |
501 [Test] | |
502 public void CloneOneofField() | |
503 { | |
504 var original = new TestAllTypes | |
505 { | |
506 OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb =
20 } | |
507 }; | |
508 | |
509 var clone = original.Clone(); | |
510 Assert.AreNotSame(original, clone); | |
511 Assert.AreEqual(original, clone); | |
512 | |
513 // We should have cloned the message | |
514 original.OneofNestedMessage.Bb = 30; | |
515 Assert.AreNotEqual(original, clone); | |
516 } | |
517 | |
518 [Test] | |
519 public void OneofProperties() | |
520 { | |
521 // Switch the oneof case between each of the different options, and
check everything behaves | |
522 // as expected in each case. | |
523 var message = new TestAllTypes(); | |
524 Assert.AreEqual("", message.OneofString); | |
525 Assert.AreEqual(0, message.OneofUint32); | |
526 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
527 Assert.IsNull(message.OneofNestedMessage); | |
528 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.Oneof
FieldCase); | |
529 | |
530 message.OneofString = "sample"; | |
531 Assert.AreEqual("sample", message.OneofString); | |
532 Assert.AreEqual(0, message.OneofUint32); | |
533 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
534 Assert.IsNull(message.OneofNestedMessage); | |
535 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, messag
e.OneofFieldCase); | |
536 | |
537 var bytes = ByteString.CopyFrom(1, 2, 3); | |
538 message.OneofBytes = bytes; | |
539 Assert.AreEqual("", message.OneofString); | |
540 Assert.AreEqual(0, message.OneofUint32); | |
541 Assert.AreEqual(bytes, message.OneofBytes); | |
542 Assert.IsNull(message.OneofNestedMessage); | |
543 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message
.OneofFieldCase); | |
544 | |
545 message.OneofUint32 = 20; | |
546 Assert.AreEqual("", message.OneofString); | |
547 Assert.AreEqual(20, message.OneofUint32); | |
548 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
549 Assert.IsNull(message.OneofNestedMessage); | |
550 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, messag
e.OneofFieldCase); | |
551 | |
552 var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 }
; | |
553 message.OneofNestedMessage = nestedMessage; | |
554 Assert.AreEqual("", message.OneofString); | |
555 Assert.AreEqual(0, message.OneofUint32); | |
556 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
557 Assert.AreEqual(nestedMessage, message.OneofNestedMessage); | |
558 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage,
message.OneofFieldCase); | |
559 | |
560 message.ClearOneofField(); | |
561 Assert.AreEqual("", message.OneofString); | |
562 Assert.AreEqual(0, message.OneofUint32); | |
563 Assert.AreEqual(ByteString.Empty, message.OneofBytes); | |
564 Assert.IsNull(message.OneofNestedMessage); | |
565 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.Oneof
FieldCase); | |
566 } | |
567 | |
568 [Test] | |
569 public void OneofSerialization_NonDefaultValue() | |
570 { | |
571 var message = new TestAllTypes(); | |
572 message.OneofString = "this would take a bit of space"; | |
573 message.OneofUint32 = 10; | |
574 var bytes = message.ToByteArray(); | |
575 Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the
value - no string! | |
576 | |
577 var message2 = TestAllTypes.Parser.ParseFrom(bytes); | |
578 Assert.AreEqual(message, message2); | |
579 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, messag
e2.OneofFieldCase); | |
580 } | |
581 | |
582 [Test] | |
583 public void OneofSerialization_DefaultValue() | |
584 { | |
585 var message = new TestAllTypes(); | |
586 message.OneofString = "this would take a bit of space"; | |
587 message.OneofUint32 = 0; // This is the default value for UInt32; no
rmally wouldn't be serialized | |
588 var bytes = message.ToByteArray(); | |
589 Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the
value - it's still serialized | |
590 | |
591 var message2 = TestAllTypes.Parser.ParseFrom(bytes); | |
592 Assert.AreEqual(message, message2); | |
593 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, messag
e2.OneofFieldCase); | |
594 } | |
595 | |
596 [Test] | |
597 public void IgnoreUnknownFields_RealDataStillRead() | |
598 { | |
599 var message = SampleMessages.CreateFullTestAllTypes(); | |
600 var stream = new MemoryStream(); | |
601 var output = new CodedOutputStream(stream); | |
602 var unusedFieldNumber = 23456; | |
603 Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().S
elect(x => x.FieldNumber).Contains(unusedFieldNumber)); | |
604 output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimit
ed); | |
605 output.WriteString("ignore me"); | |
606 message.WriteTo(output); | |
607 output.Flush(); | |
608 | |
609 stream.Position = 0; | |
610 var parsed = TestAllTypes.Parser.ParseFrom(stream); | |
611 Assert.AreEqual(message, parsed); | |
612 } | |
613 | |
614 [Test] | |
615 public void IgnoreUnknownFields_AllTypes() | |
616 { | |
617 // Simple way of ensuring we can skip all kinds of fields. | |
618 var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); | |
619 var empty = Empty.Parser.ParseFrom(data); | |
620 Assert.AreEqual(new Empty(), empty); | |
621 } | |
622 | |
623 // This was originally seen as a conformance test failure. | |
624 [Test] | |
625 public void TruncatedMessageFieldThrows() | |
626 { | |
627 // 130, 3 is the message tag | |
628 // 1 is the data length - but there's no data. | |
629 var data = new byte[] { 130, 3, 1 }; | |
630 Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Par
ser.ParseFrom(data)); | |
631 } | |
632 | |
633 /// <summary> | |
634 /// Demonstrates current behaviour with an extraneous end group tag - se
e issue 688 | |
635 /// for details; we may want to change this. | |
636 /// </summary> | |
637 [Test] | |
638 public void ExtraEndGroupSkipped() | |
639 { | |
640 var message = SampleMessages.CreateFullTestAllTypes(); | |
641 var stream = new MemoryStream(); | |
642 var output = new CodedOutputStream(stream); | |
643 | |
644 output.WriteTag(100, WireFormat.WireType.EndGroup); | |
645 output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.Wi
reType.Fixed32); | |
646 output.WriteFixed32(123); | |
647 | |
648 output.Flush(); | |
649 | |
650 stream.Position = 0; | |
651 var parsed = TestAllTypes.Parser.ParseFrom(stream); | |
652 Assert.AreEqual(new TestAllTypes { SingleFixed32 = 123 }, parsed); | |
653 } | |
654 } | |
655 } | |
OLD | NEW |