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