• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2015 Google Inc.  All rights reserved.
4 //
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file or at
7 // https://developers.google.com/open-source/licenses/bsd
8 #endregion
9 
10 using System;
11 using System.IO;
12 using Google.Protobuf.TestProtos;
13 using NUnit.Framework;
14 using System.Collections;
15 using System.Collections.Generic;
16 using System.Linq;
17 using Google.Protobuf.WellKnownTypes;
18 
19 namespace Google.Protobuf
20 {
21     /// <summary>
22     /// Tests around the generated TestAllTypes message.
23     /// </summary>
24     public class GeneratedMessageTest
25     {
26         [Test]
EmptyMessageFieldDistinctFromMissingMessageField()27         public void EmptyMessageFieldDistinctFromMissingMessageField()
28         {
29             // This demonstrates what we're really interested in...
30             var message1 = new TestAllTypes { SingleForeignMessage = new ForeignMessage() };
31             var message2 = new TestAllTypes(); // SingleForeignMessage is null
32             EqualityTester.AssertInequality(message1, message2);
33         }
34 
35         [Test]
DefaultValues()36         public void DefaultValues()
37         {
38             // Single fields
39             var message = new TestAllTypes();
40             Assert.AreEqual(false, message.SingleBool);
41             Assert.AreEqual(ByteString.Empty, message.SingleBytes);
42             Assert.AreEqual(0.0, message.SingleDouble);
43             Assert.AreEqual(0, message.SingleFixed32);
44             Assert.AreEqual(0L, message.SingleFixed64);
45             Assert.AreEqual(0.0f, message.SingleFloat);
46             Assert.AreEqual(ForeignEnum.ForeignUnspecified, message.SingleForeignEnum);
47             Assert.IsNull(message.SingleForeignMessage);
48             Assert.AreEqual(ImportEnum.Unspecified, message.SingleImportEnum);
49             Assert.IsNull(message.SingleImportMessage);
50             Assert.AreEqual(0, message.SingleInt32);
51             Assert.AreEqual(0L, message.SingleInt64);
52             Assert.AreEqual(TestAllTypes.Types.NestedEnum.Unspecified, message.SingleNestedEnum);
53             Assert.IsNull(message.SingleNestedMessage);
54             Assert.IsNull(message.SinglePublicImportMessage);
55             Assert.AreEqual(0, message.SingleSfixed32);
56             Assert.AreEqual(0L, message.SingleSfixed64);
57             Assert.AreEqual(0, message.SingleSint32);
58             Assert.AreEqual(0L, message.SingleSint64);
59             Assert.AreEqual("", message.SingleString);
60             Assert.AreEqual(0U, message.SingleUint32);
61             Assert.AreEqual(0UL, message.SingleUint64);
62 
63             // Repeated fields
64             Assert.AreEqual(0, message.RepeatedBool.Count);
65             Assert.AreEqual(0, message.RepeatedBytes.Count);
66             Assert.AreEqual(0, message.RepeatedDouble.Count);
67             Assert.AreEqual(0, message.RepeatedFixed32.Count);
68             Assert.AreEqual(0, message.RepeatedFixed64.Count);
69             Assert.AreEqual(0, message.RepeatedFloat.Count);
70             Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
71             Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
72             Assert.AreEqual(0, message.RepeatedImportEnum.Count);
73             Assert.AreEqual(0, message.RepeatedImportMessage.Count);
74             Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
75             Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
76             Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count);
77             Assert.AreEqual(0, message.RepeatedSfixed32.Count);
78             Assert.AreEqual(0, message.RepeatedSfixed64.Count);
79             Assert.AreEqual(0, message.RepeatedSint32.Count);
80             Assert.AreEqual(0, message.RepeatedSint64.Count);
81             Assert.AreEqual(0, message.RepeatedString.Count);
82             Assert.AreEqual(0, message.RepeatedUint32.Count);
83             Assert.AreEqual(0, message.RepeatedUint64.Count);
84 
85             // Oneof fields
86             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
87             Assert.AreEqual(0, message.OneofUint32);
88             Assert.AreEqual("", message.OneofString);
89             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
90             Assert.IsNull(message.OneofNestedMessage);
91         }
92 
93         [Test]
NullStringAndBytesRejected()94         public void NullStringAndBytesRejected()
95         {
96             var message = new TestAllTypes();
97             Assert.Throws<ArgumentNullException>(() => message.SingleString = null);
98             Assert.Throws<ArgumentNullException>(() => message.OneofString = null);
99             Assert.Throws<ArgumentNullException>(() => message.SingleBytes = null);
100             Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null);
101         }
102 
103         [Test]
RoundTrip_Empty()104         public void RoundTrip_Empty()
105         {
106             var message = new TestAllTypes();
107             // Without setting any values, there's nothing to write.
108             byte[] bytes = message.ToByteArray();
109             Assert.AreEqual(0, bytes.Length);
110             TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
111             Assert.AreEqual(message, parsed);
112         }
113 
114         [Test]
RoundTrip_SingleValues()115         public void RoundTrip_SingleValues()
116         {
117             var message = new TestAllTypes
118             {
119                 SingleBool = true,
120                 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
121                 SingleDouble = 23.5,
122                 SingleFixed32 = 23,
123                 SingleFixed64 = 1234567890123,
124                 SingleFloat = 12.25f,
125                 SingleForeignEnum = ForeignEnum.ForeignBar,
126                 SingleForeignMessage = new ForeignMessage { C = 10 },
127                 SingleImportEnum = ImportEnum.ImportBaz,
128                 SingleImportMessage = new ImportMessage { D = 20 },
129                 SingleInt32 = 100,
130                 SingleInt64 = 3210987654321,
131                 SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
132                 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
133                 SinglePublicImportMessage = new PublicImportMessage { E = 54 },
134                 SingleSfixed32 = -123,
135                 SingleSfixed64 = -12345678901234,
136                 SingleSint32 = -456,
137                 SingleSint64 = -12345678901235,
138                 SingleString = "test",
139                 SingleUint32 = uint.MaxValue,
140                 SingleUint64 = ulong.MaxValue
141             };
142 
143             byte[] bytes = message.ToByteArray();
144             TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
145             Assert.AreEqual(message, parsed);
146         }
147 
148         [Test]
RoundTrip_RepeatedValues()149         public void RoundTrip_RepeatedValues()
150         {
151             var message = new TestAllTypes
152             {
153                 RepeatedBool = { true, false },
154                 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
155                 RepeatedDouble = { -12.25, 23.5 },
156                 RepeatedFixed32 = { uint.MaxValue, 23 },
157                 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
158                 RepeatedFloat = { 100f, 12.25f },
159                 RepeatedForeignEnum = { ForeignEnum.ForeignFoo, ForeignEnum.ForeignBar },
160                 RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
161                 RepeatedImportEnum = { ImportEnum.ImportBaz, ImportEnum.Unspecified },
162                 RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
163                 RepeatedInt32 = { 100, 200 },
164                 RepeatedInt64 = { 3210987654321, long.MaxValue },
165                 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
166                 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
167                 RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
168                 RepeatedSfixed32 = { -123, 123 },
169                 RepeatedSfixed64 = { -12345678901234, 12345678901234 },
170                 RepeatedSint32 = { -456, 100 },
171                 RepeatedSint64 = { -12345678901235, 123 },
172                 RepeatedString = { "foo", "bar" },
173                 RepeatedUint32 = { uint.MaxValue, uint.MinValue },
174                 RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
175             };
176 
177             byte[] bytes = message.ToByteArray();
178             TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
179             Assert.AreEqual(message, parsed);
180         }
181 
182         // Note that not every map within map_unittest_proto3 is used. They all go through very
183         // similar code paths. The fact that all maps are present is validation that we have codecs
184         // for every type.
185         [Test]
RoundTrip_Maps()186         public void RoundTrip_Maps()
187         {
188             var message = new TestMap
189             {
190                 MapBoolBool = {
191                     { false, true },
192                     { true, false }
193                 },
194                 MapInt32Bytes = {
195                     { 5, ByteString.CopyFrom(6, 7, 8) },
196                     { 25, ByteString.CopyFrom(1, 2, 3, 4, 5) },
197                     { 10, ByteString.Empty }
198                 },
199                 MapInt32ForeignMessage = {
200                     { 0, new ForeignMessage { C = 10 } },
201                     { 5, new ForeignMessage() },
202                 },
203                 MapInt32Enum = {
204                     { 1, MapEnum.Bar },
205                     { 2000, MapEnum.Foo }
206                 }
207             };
208 
209             byte[] bytes = message.ToByteArray();
210             TestMap parsed = TestMap.Parser.ParseFrom(bytes);
211             Assert.AreEqual(message, parsed);
212         }
213 
214         [Test]
MapWithEmptyEntry()215         public void MapWithEmptyEntry()
216         {
217             var message = new TestMap
218             {
219                 MapInt32Bytes = { { 0, ByteString.Empty } }
220             };
221 
222             byte[] bytes = message.ToByteArray();
223             Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)
224 
225             var parsed = TestMap.Parser.ParseFrom(bytes);
226             Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
227             Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
228         }
229 
230         [Test]
MapWithOnlyValue()231         public void MapWithOnlyValue()
232         {
233             // Hand-craft the stream to contain a single entry with just a value.
234             var memoryStream = new MemoryStream();
235             var output = new CodedOutputStream(memoryStream);
236             output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
237             var nestedMessage = new ForeignMessage { C = 20 };
238             // Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
239             output.WriteLength(2 + nestedMessage.CalculateSize());
240             output.WriteTag(2, WireFormat.WireType.LengthDelimited);
241             output.WriteMessage(nestedMessage);
242             output.Flush();
243 
244             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
245             Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);
246         }
247 
248         [Test]
MapWithOnlyKey_PrimitiveValue()249         public void MapWithOnlyKey_PrimitiveValue()
250         {
251             // Hand-craft the stream to contain a single entry with just a key.
252             var memoryStream = new MemoryStream();
253             var output = new CodedOutputStream(memoryStream);
254             output.WriteTag(TestMap.MapInt32DoubleFieldNumber, WireFormat.WireType.LengthDelimited);
255             int key = 10;
256             output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
257             output.WriteTag(1, WireFormat.WireType.Varint);
258             output.WriteInt32(key);
259             output.Flush();
260 
261             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
262             Assert.AreEqual(0.0, parsed.MapInt32Double[key]);
263         }
264 
265         [Test]
MapWithOnlyKey_MessageValue()266         public void MapWithOnlyKey_MessageValue()
267         {
268             // Hand-craft the stream to contain a single entry with just a key.
269             var memoryStream = new MemoryStream();
270             var output = new CodedOutputStream(memoryStream);
271             output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
272             int key = 10;
273             output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
274             output.WriteTag(1, WireFormat.WireType.Varint);
275             output.WriteInt32(key);
276             output.Flush();
277 
278             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
279             Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);
280         }
281 
282         [Test]
MapIgnoresExtraFieldsWithinEntryMessages()283         public void MapIgnoresExtraFieldsWithinEntryMessages()
284         {
285             // Hand-craft the stream to contain a single entry with three fields
286             var memoryStream = new MemoryStream();
287             var output = new CodedOutputStream(memoryStream);
288 
289             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
290 
291             var key = 10; // Field 1
292             var value = 20; // Field 2
293             var extra = 30; // Field 3
294 
295             // Each field can be represented in a single byte, with a single byte tag.
296             // Total message size: 6 bytes.
297             output.WriteLength(6);
298             output.WriteTag(1, WireFormat.WireType.Varint);
299             output.WriteInt32(key);
300             output.WriteTag(2, WireFormat.WireType.Varint);
301             output.WriteInt32(value);
302             output.WriteTag(3, WireFormat.WireType.Varint);
303             output.WriteInt32(extra);
304             output.Flush();
305 
306             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
307             Assert.AreEqual(value, parsed.MapInt32Int32[key]);
308         }
309 
310         [Test]
MapFieldOrderIsIrrelevant()311         public void MapFieldOrderIsIrrelevant()
312         {
313             var memoryStream = new MemoryStream();
314             var output = new CodedOutputStream(memoryStream);
315 
316             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
317 
318             var key = 10;
319             var value = 20;
320 
321             // Each field can be represented in a single byte, with a single byte tag.
322             // Total message size: 4 bytes.
323             output.WriteLength(4);
324             output.WriteTag(2, WireFormat.WireType.Varint);
325             output.WriteInt32(value);
326             output.WriteTag(1, WireFormat.WireType.Varint);
327             output.WriteInt32(key);
328             output.Flush();
329 
330             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
331             Assert.AreEqual(value, parsed.MapInt32Int32[key]);
332         }
333 
334         [Test]
MapNonContiguousEntries()335         public void MapNonContiguousEntries()
336         {
337             var memoryStream = new MemoryStream();
338             var output = new CodedOutputStream(memoryStream);
339 
340             // Message structure:
341             // Entry for MapInt32Int32
342             // Entry for MapStringString
343             // Entry for MapInt32Int32
344 
345             // First entry
346             var key1 = 10;
347             var value1 = 20;
348             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
349             output.WriteLength(4);
350             output.WriteTag(1, WireFormat.WireType.Varint);
351             output.WriteInt32(key1);
352             output.WriteTag(2, WireFormat.WireType.Varint);
353             output.WriteInt32(value1);
354 
355             // Second entry
356             var key2 = "a";
357             var value2 = "b";
358             output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
359             output.WriteLength(6); // 3 bytes per entry: tag, size, character
360             output.WriteTag(1, WireFormat.WireType.LengthDelimited);
361             output.WriteString(key2);
362             output.WriteTag(2, WireFormat.WireType.LengthDelimited);
363             output.WriteString(value2);
364 
365             // Third entry
366             var key3 = 15;
367             var value3 = 25;
368             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
369             output.WriteLength(4);
370             output.WriteTag(1, WireFormat.WireType.Varint);
371             output.WriteInt32(key3);
372             output.WriteTag(2, WireFormat.WireType.Varint);
373             output.WriteInt32(value3);
374 
375             output.Flush();
376             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
377             var expected = new TestMap
378             {
379                 MapInt32Int32 = { { key1, value1 }, { key3, value3 } },
380                 MapStringString = { { key2, value2 } }
381             };
382             Assert.AreEqual(expected, parsed);
383         }
384 
385         [Test]
DuplicateKeys_LastEntryWins()386         public void DuplicateKeys_LastEntryWins()
387         {
388             var memoryStream = new MemoryStream();
389             var output = new CodedOutputStream(memoryStream);
390 
391             var key = 10;
392             var value1 = 20;
393             var value2 = 30;
394 
395             // First entry
396             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
397             output.WriteLength(4);
398             output.WriteTag(1, WireFormat.WireType.Varint);
399             output.WriteInt32(key);
400             output.WriteTag(2, WireFormat.WireType.Varint);
401             output.WriteInt32(value1);
402 
403             // Second entry - same key, different value
404             output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
405             output.WriteLength(4);
406             output.WriteTag(1, WireFormat.WireType.Varint);
407             output.WriteInt32(key);
408             output.WriteTag(2, WireFormat.WireType.Varint);
409             output.WriteInt32(value2);
410             output.Flush();
411 
412             var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
413             Assert.AreEqual(value2, parsed.MapInt32Int32[key]);
414         }
415 
416         [Test]
CloneSingleNonMessageValues()417         public void CloneSingleNonMessageValues()
418         {
419             var original = new TestAllTypes
420             {
421                 SingleBool = true,
422                 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
423                 SingleDouble = 23.5,
424                 SingleFixed32 = 23,
425                 SingleFixed64 = 1234567890123,
426                 SingleFloat = 12.25f,
427                 SingleInt32 = 100,
428                 SingleInt64 = 3210987654321,
429                 SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
430                 SingleSfixed32 = -123,
431                 SingleSfixed64 = -12345678901234,
432                 SingleSint32 = -456,
433                 SingleSint64 = -12345678901235,
434                 SingleString = "test",
435                 SingleUint32 = uint.MaxValue,
436                 SingleUint64 = ulong.MaxValue
437             };
438             var clone = original.Clone();
439             Assert.AreNotSame(original, clone);
440             Assert.AreEqual(original, clone);
441             // Just as a single example
442             clone.SingleInt32 = 150;
443             Assert.AreNotEqual(original, clone);
444         }
445 
446         [Test]
CloneRepeatedNonMessageValues()447         public void CloneRepeatedNonMessageValues()
448         {
449             var original = new TestAllTypes
450             {
451                 RepeatedBool = { true, false },
452                 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
453                 RepeatedDouble = { -12.25, 23.5 },
454                 RepeatedFixed32 = { uint.MaxValue, 23 },
455                 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
456                 RepeatedFloat = { 100f, 12.25f },
457                 RepeatedInt32 = { 100, 200 },
458                 RepeatedInt64 = { 3210987654321, long.MaxValue },
459                 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
460                 RepeatedSfixed32 = { -123, 123 },
461                 RepeatedSfixed64 = { -12345678901234, 12345678901234 },
462                 RepeatedSint32 = { -456, 100 },
463                 RepeatedSint64 = { -12345678901235, 123 },
464                 RepeatedString = { "foo", "bar" },
465                 RepeatedUint32 = { uint.MaxValue, uint.MinValue },
466                 RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
467             };
468 
469             var clone = original.Clone();
470             Assert.AreNotSame(original, clone);
471             Assert.AreEqual(original, clone);
472             // Just as a single example
473             clone.RepeatedDouble.Add(25.5);
474             Assert.AreNotEqual(original, clone);
475         }
476 
477         [Test]
CloneSingleMessageField()478         public void CloneSingleMessageField()
479         {
480             var original = new TestAllTypes
481             {
482                 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
483             };
484 
485             var clone = original.Clone();
486             Assert.AreNotSame(original, clone);
487             Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
488             Assert.AreEqual(original, clone);
489 
490             clone.SingleNestedMessage.Bb = 30;
491             Assert.AreNotEqual(original, clone);
492         }
493 
494         [Test]
CloneRepeatedMessageField()495         public void CloneRepeatedMessageField()
496         {
497             var original = new TestAllTypes
498             {
499                 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
500             };
501 
502             var clone = original.Clone();
503             Assert.AreNotSame(original, clone);
504             Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
505             Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
506             Assert.AreEqual(original, clone);
507 
508             clone.RepeatedNestedMessage[0].Bb = 30;
509             Assert.AreNotEqual(original, clone);
510         }
511 
512         [Test]
CloneOneofField()513         public void CloneOneofField()
514         {
515             var original = new TestAllTypes
516             {
517                 OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
518             };
519 
520             var clone = original.Clone();
521             Assert.AreNotSame(original, clone);
522             Assert.AreEqual(original, clone);
523 
524             // We should have cloned the message
525             original.OneofNestedMessage.Bb = 30;
526             Assert.AreNotEqual(original, clone);
527         }
528 
529         [Test]
OneofProperties()530         public void OneofProperties()
531         {
532             // Switch the oneof case between each of the different options, and check everything behaves
533             // as expected in each case.
534             var message = new TestAllTypes();
535             Assert.AreEqual("", message.OneofString);
536             Assert.AreEqual(0, message.OneofUint32);
537             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
538             Assert.IsNull(message.OneofNestedMessage);
539             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
540 
541             message.OneofString = "sample";
542             Assert.AreEqual("sample", message.OneofString);
543             Assert.AreEqual(0, message.OneofUint32);
544             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
545             Assert.IsNull(message.OneofNestedMessage);
546             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
547 
548             var bytes = ByteString.CopyFrom(1, 2, 3);
549             message.OneofBytes = bytes;
550             Assert.AreEqual("", message.OneofString);
551             Assert.AreEqual(0, message.OneofUint32);
552             Assert.AreEqual(bytes, message.OneofBytes);
553             Assert.IsNull(message.OneofNestedMessage);
554             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
555 
556             message.OneofUint32 = 20;
557             Assert.AreEqual("", message.OneofString);
558             Assert.AreEqual(20, message.OneofUint32);
559             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
560             Assert.IsNull(message.OneofNestedMessage);
561             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
562 
563             var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
564             message.OneofNestedMessage = nestedMessage;
565             Assert.AreEqual("", message.OneofString);
566             Assert.AreEqual(0, message.OneofUint32);
567             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
568             Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
569             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
570 
571             message.ClearOneofField();
572             Assert.AreEqual("", message.OneofString);
573             Assert.AreEqual(0, message.OneofUint32);
574             Assert.AreEqual(ByteString.Empty, message.OneofBytes);
575             Assert.IsNull(message.OneofNestedMessage);
576             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
577         }
578 
579         [Test]
Oneof_DefaultValuesNotEqual()580         public void Oneof_DefaultValuesNotEqual()
581         {
582             var message1 = new TestAllTypes { OneofString = "" };
583             var message2 = new TestAllTypes { OneofUint32 = 0 };
584             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message1.OneofFieldCase);
585             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
586             Assert.AreNotEqual(message1, message2);
587         }
588 
589         [Test]
OneofSerialization_NonDefaultValue()590         public void OneofSerialization_NonDefaultValue()
591         {
592             var message = new TestAllTypes();
593             message.OneofString = "this would take a bit of space";
594             message.OneofUint32 = 10;
595             var bytes = message.ToByteArray();
596             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
597 
598             var message2 = TestAllTypes.Parser.ParseFrom(bytes);
599             Assert.AreEqual(message, message2);
600             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
601         }
602 
603         [Test]
OneofSerialization_DefaultValue()604         public void OneofSerialization_DefaultValue()
605         {
606             var message = new TestAllTypes();
607             message.OneofString = "this would take a bit of space";
608             message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
609             var bytes = message.ToByteArray();
610             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
611 
612             var message2 = TestAllTypes.Parser.ParseFrom(bytes);
613             Assert.AreEqual(message, message2);
614             Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
615         }
616 
617         [Test]
DiscardUnknownFields_RealDataStillRead()618         public void DiscardUnknownFields_RealDataStillRead()
619         {
620             var message = SampleMessages.CreateFullTestAllTypes();
621             var stream = new MemoryStream();
622             var output = new CodedOutputStream(stream);
623             var unusedFieldNumber = 23456;
624             Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
625             output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
626             output.WriteString("ignore me");
627             message.WriteTo(output);
628             output.Flush();
629 
630             stream.Position = 0;
631             var parsed = TestAllTypes.Parser.ParseFrom(stream);
632 	    // TODO: Add test back after DiscardUnknownFields is supported
633             // Assert.AreEqual(message, parsed);
634         }
635 
636         [Test]
DiscardUnknownFields_AllTypes()637         public void DiscardUnknownFields_AllTypes()
638         {
639             // Simple way of ensuring we can skip all kinds of fields.
640             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
641             var empty = Empty.Parser.ParseFrom(data);
642 	    // TODO: Add test back after DiscardUnknownField is supported.
643             // Assert.AreEqual(new Empty(), empty);
644         }
645 
646         // This was originally seen as a conformance test failure.
647         [Test]
TruncatedMessageFieldThrows()648         public void TruncatedMessageFieldThrows()
649         {
650             // 130, 3 is the message tag
651             // 1 is the data length - but there's no data.
652             var data = new byte[] { 130, 3, 1 };
653             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
654         }
655 
656         /// <summary>
657         /// Demonstrates current behaviour with an extraneous end group tag - see issue 688
658         /// for details; we may want to change this.
659         /// </summary>
660         [Test]
ExtraEndGroupThrows()661         public void ExtraEndGroupThrows()
662         {
663             var message = SampleMessages.CreateFullTestAllTypes();
664             var stream = new MemoryStream();
665             var output = new CodedOutputStream(stream);
666 
667             output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.WireType.Fixed32);
668             output.WriteFixed32(123);
669             output.WriteTag(100, WireFormat.WireType.EndGroup);
670 
671             output.Flush();
672 
673             stream.Position = 0;
674             Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream));
675         }
676 
677         [Test]
CustomDiagnosticMessage_DirectToStringCall()678         public void CustomDiagnosticMessage_DirectToStringCall()
679         {
680             var message = new ForeignMessage { C = 31 };
681             Assert.AreEqual("{ \"c\": 31, \"@cInHex\": \"1f\" }", message.ToString());
682             Assert.AreEqual("{ \"c\": 31 }", JsonFormatter.Default.Format(message));
683         }
684 
685         [Test]
CustomDiagnosticMessage_Nested()686         public void CustomDiagnosticMessage_Nested()
687         {
688             var message = new TestAllTypes { SingleForeignMessage = new ForeignMessage { C = 16 } };
689             Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16, \"@cInHex\": \"10\" } }", message.ToString());
690             Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16 } }", JsonFormatter.Default.Format(message));
691         }
692 
693         [Test]
CustomDiagnosticMessage_DirectToTextWriterCall()694         public void CustomDiagnosticMessage_DirectToTextWriterCall()
695         {
696             var message = new ForeignMessage { C = 31 };
697             var writer = new StringWriter();
698             JsonFormatter.Default.Format(message, writer);
699             Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
700         }
701     }
702 }
703