1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2008 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 Google.Protobuf.Buffers; 37 using NUnit.Framework; 38 39 namespace Google.Protobuf 40 { 41 public class CodedOutputStreamTest 42 { 43 /// <summary> 44 /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and 45 /// checks that the result matches the given bytes 46 /// </summary> AssertWriteVarint(byte[] data, ulong value)47 private static void AssertWriteVarint(byte[] data, ulong value) 48 { 49 // Only do 32-bit write if the value fits in 32 bits. 50 if ((value >> 32) == 0) 51 { 52 // CodedOutputStream 53 MemoryStream rawOutput = new MemoryStream(); 54 CodedOutputStream output = new CodedOutputStream(rawOutput); 55 output.WriteRawVarint32((uint) value); 56 output.Flush(); 57 Assert.AreEqual(data, rawOutput.ToArray()); 58 59 // IBufferWriter 60 var bufferWriter = new ArrayBufferWriter<byte>(); 61 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 62 ctx.WriteUInt32((uint) value); 63 ctx.Flush(); 64 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 65 66 // Also try computing size. 67 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value)); 68 } 69 70 { 71 // CodedOutputStream 72 MemoryStream rawOutput = new MemoryStream(); 73 CodedOutputStream output = new CodedOutputStream(rawOutput); 74 output.WriteRawVarint64(value); 75 output.Flush(); 76 Assert.AreEqual(data, rawOutput.ToArray()); 77 78 // IBufferWriter 79 var bufferWriter = new ArrayBufferWriter<byte>(); 80 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 81 ctx.WriteUInt64(value); 82 ctx.Flush(); 83 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 84 85 // Also try computing size. 86 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value)); 87 } 88 89 // Try different buffer sizes. 90 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) 91 { 92 // Only do 32-bit write if the value fits in 32 bits. 93 if ((value >> 32) == 0) 94 { 95 MemoryStream rawOutput = new MemoryStream(); 96 CodedOutputStream output = 97 new CodedOutputStream(rawOutput, bufferSize); 98 output.WriteRawVarint32((uint) value); 99 output.Flush(); 100 Assert.AreEqual(data, rawOutput.ToArray()); 101 102 var bufferWriter = new ArrayBufferWriter<byte>(); 103 bufferWriter.MaxGrowBy = bufferSize; 104 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 105 ctx.WriteUInt32((uint) value); 106 ctx.Flush(); 107 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 108 } 109 110 { 111 MemoryStream rawOutput = new MemoryStream(); 112 CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize); 113 output.WriteRawVarint64(value); 114 output.Flush(); 115 Assert.AreEqual(data, rawOutput.ToArray()); 116 117 var bufferWriter = new ArrayBufferWriter<byte>(); 118 bufferWriter.MaxGrowBy = bufferSize; 119 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 120 ctx.WriteUInt64(value); 121 ctx.Flush(); 122 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 123 } 124 125 } 126 } 127 128 /// <summary> 129 /// Tests WriteRawVarint32() and WriteRawVarint64() 130 /// </summary> 131 [Test] WriteVarint()132 public void WriteVarint() 133 { 134 AssertWriteVarint(new byte[] {0x00}, 0); 135 AssertWriteVarint(new byte[] {0x01}, 1); 136 AssertWriteVarint(new byte[] {0x7f}, 127); 137 // 14882 138 AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7)); 139 // 2961488830 140 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b}, 141 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | 142 (0x0bL << 28)); 143 144 // 64-bit 145 // 7256456126 146 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b}, 147 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | 148 (0x1bL << 28)); 149 // 41256202580718336 150 AssertWriteVarint( 151 new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, 152 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | 153 (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49)); 154 // 11964378330978735131 155 AssertWriteVarint( 156 new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, 157 unchecked((ulong) 158 ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | 159 (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) | 160 (0x05L << 49) | (0x26L << 56) | (0x01L << 63)))); 161 } 162 163 /// <summary> 164 /// Parses the given bytes using WriteRawLittleEndian32() and checks 165 /// that the result matches the given value. 166 /// </summary> AssertWriteLittleEndian32(byte[] data, uint value)167 private static void AssertWriteLittleEndian32(byte[] data, uint value) 168 { 169 { 170 var rawOutput = new MemoryStream(); 171 var output = new CodedOutputStream(rawOutput); 172 output.WriteRawLittleEndian32(value); 173 output.Flush(); 174 Assert.AreEqual(data, rawOutput.ToArray()); 175 176 var bufferWriter = new ArrayBufferWriter<byte>(); 177 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 178 ctx.WriteFixed32(value); 179 ctx.Flush(); 180 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 181 } 182 183 // Try different buffer sizes. 184 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) 185 { 186 var rawOutput = new MemoryStream(); 187 var output = new CodedOutputStream(rawOutput, bufferSize); 188 output.WriteRawLittleEndian32(value); 189 output.Flush(); 190 Assert.AreEqual(data, rawOutput.ToArray()); 191 192 var bufferWriter = new ArrayBufferWriter<byte>(); 193 bufferWriter.MaxGrowBy = bufferSize; 194 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 195 ctx.WriteFixed32(value); 196 ctx.Flush(); 197 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 198 } 199 } 200 201 /// <summary> 202 /// Parses the given bytes using WriteRawLittleEndian64() and checks 203 /// that the result matches the given value. 204 /// </summary> AssertWriteLittleEndian64(byte[] data, ulong value)205 private static void AssertWriteLittleEndian64(byte[] data, ulong value) 206 { 207 { 208 var rawOutput = new MemoryStream(); 209 var output = new CodedOutputStream(rawOutput); 210 output.WriteRawLittleEndian64(value); 211 output.Flush(); 212 Assert.AreEqual(data, rawOutput.ToArray()); 213 214 var bufferWriter = new ArrayBufferWriter<byte>(); 215 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 216 ctx.WriteFixed64(value); 217 ctx.Flush(); 218 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 219 } 220 221 // Try different block sizes. 222 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) 223 { 224 var rawOutput = new MemoryStream(); 225 var output = new CodedOutputStream(rawOutput, blockSize); 226 output.WriteRawLittleEndian64(value); 227 output.Flush(); 228 Assert.AreEqual(data, rawOutput.ToArray()); 229 230 var bufferWriter = new ArrayBufferWriter<byte>(); 231 bufferWriter.MaxGrowBy = blockSize; 232 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 233 ctx.WriteFixed64(value); 234 ctx.Flush(); 235 Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); 236 } 237 } 238 239 /// <summary> 240 /// Tests writeRawLittleEndian32() and writeRawLittleEndian64(). 241 /// </summary> 242 [Test] WriteLittleEndian()243 public void WriteLittleEndian() 244 { 245 AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678); 246 AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0); 247 248 AssertWriteLittleEndian64( 249 new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}, 250 0x123456789abcdef0L); 251 AssertWriteLittleEndian64( 252 new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a}, 253 0x9abcdef012345678UL); 254 } 255 256 [Test] WriteWholeMessage_VaryingBlockSizes()257 public void WriteWholeMessage_VaryingBlockSizes() 258 { 259 TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); 260 261 byte[] rawBytes = message.ToByteArray(); 262 263 // Try different block sizes. 264 for (int blockSize = 1; blockSize < 256; blockSize *= 2) 265 { 266 MemoryStream rawOutput = new MemoryStream(); 267 CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize); 268 message.WriteTo(output); 269 output.Flush(); 270 Assert.AreEqual(rawBytes, rawOutput.ToArray()); 271 272 var bufferWriter = new ArrayBufferWriter<byte>(); 273 bufferWriter.MaxGrowBy = blockSize; 274 message.WriteTo(bufferWriter); 275 Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); 276 } 277 } 278 279 [Test] WriteContext_WritesWithFlushes()280 public void WriteContext_WritesWithFlushes() 281 { 282 TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); 283 284 MemoryStream expectedOutput = new MemoryStream(); 285 CodedOutputStream output = new CodedOutputStream(expectedOutput); 286 output.WriteMessage(message); 287 output.Flush(); 288 byte[] expectedBytes1 = expectedOutput.ToArray(); 289 290 output.WriteMessage(message); 291 output.Flush(); 292 byte[] expectedBytes2 = expectedOutput.ToArray(); 293 294 var bufferWriter = new ArrayBufferWriter<byte>(); 295 WriteContext.Initialize(bufferWriter, out WriteContext ctx); 296 ctx.WriteMessage(message); 297 ctx.Flush(); 298 Assert.AreEqual(expectedBytes1, bufferWriter.WrittenSpan.ToArray()); 299 300 ctx.WriteMessage(message); 301 ctx.Flush(); 302 Assert.AreEqual(expectedBytes2, bufferWriter.WrittenSpan.ToArray()); 303 } 304 305 [Test] EncodeZigZag32()306 public void EncodeZigZag32() 307 { 308 Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0)); 309 Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1)); 310 Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1)); 311 Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2)); 312 Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF)); 313 Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000))); 314 Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF)); 315 Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000))); 316 } 317 318 [Test] EncodeZigZag64()319 public void EncodeZigZag64() 320 { 321 Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0)); 322 Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1)); 323 Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1)); 324 Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2)); 325 Assert.AreEqual(0x000000007FFFFFFEuL, 326 WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); 327 Assert.AreEqual(0x000000007FFFFFFFuL, 328 WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); 329 Assert.AreEqual(0x00000000FFFFFFFEuL, 330 WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); 331 Assert.AreEqual(0x00000000FFFFFFFFuL, 332 WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); 333 Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, 334 WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); 335 Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, 336 WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); 337 } 338 339 [Test] RoundTripZigZag32()340 public void RoundTripZigZag32() 341 { 342 // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) 343 // were chosen semi-randomly via keyboard bashing. 344 Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0))); 345 Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1))); 346 Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1))); 347 Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927))); 348 Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612))); 349 } 350 351 [Test] RoundTripZigZag64()352 public void RoundTripZigZag64() 353 { 354 Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0))); 355 Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1))); 356 Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1))); 357 Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927))); 358 Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612))); 359 360 Assert.AreEqual(856912304801416L, 361 ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L))); 362 Assert.AreEqual(-75123905439571256L, 363 ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L))); 364 } 365 366 [Test] TestNegativeEnumNoTag()367 public void TestNegativeEnumNoTag() 368 { 369 Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2)); 370 Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue)); 371 372 byte[] bytes = new byte[10]; 373 CodedOutputStream output = new CodedOutputStream(bytes); 374 output.WriteEnum((int) SampleEnum.NegativeValue); 375 376 Assert.AreEqual(0, output.SpaceLeft); 377 Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); 378 } 379 380 [Test] TestCodedInputOutputPosition()381 public void TestCodedInputOutputPosition() 382 { 383 byte[] content = new byte[110]; 384 for (int i = 0; i < content.Length; i++) 385 content[i] = (byte)i; 386 387 byte[] child = new byte[120]; 388 { 389 MemoryStream ms = new MemoryStream(child); 390 CodedOutputStream cout = new CodedOutputStream(ms, 20); 391 // Field 11: numeric value: 500 392 cout.WriteTag(11, WireFormat.WireType.Varint); 393 Assert.AreEqual(1, cout.Position); 394 cout.WriteInt32(500); 395 Assert.AreEqual(3, cout.Position); 396 //Field 12: length delimited 120 bytes 397 cout.WriteTag(12, WireFormat.WireType.LengthDelimited); 398 Assert.AreEqual(4, cout.Position); 399 cout.WriteBytes(ByteString.CopyFrom(content)); 400 Assert.AreEqual(115, cout.Position); 401 // Field 13: fixed numeric value: 501 402 cout.WriteTag(13, WireFormat.WireType.Fixed32); 403 Assert.AreEqual(116, cout.Position); 404 cout.WriteSFixed32(501); 405 Assert.AreEqual(120, cout.Position); 406 cout.Flush(); 407 } 408 409 byte[] bytes = new byte[130]; 410 { 411 CodedOutputStream cout = new CodedOutputStream(bytes); 412 // Field 1: numeric value: 500 413 cout.WriteTag(1, WireFormat.WireType.Varint); 414 Assert.AreEqual(1, cout.Position); 415 cout.WriteInt32(500); 416 Assert.AreEqual(3, cout.Position); 417 //Field 2: length delimited 120 bytes 418 cout.WriteTag(2, WireFormat.WireType.LengthDelimited); 419 Assert.AreEqual(4, cout.Position); 420 cout.WriteBytes(ByteString.CopyFrom(child)); 421 Assert.AreEqual(125, cout.Position); 422 // Field 3: fixed numeric value: 500 423 cout.WriteTag(3, WireFormat.WireType.Fixed32); 424 Assert.AreEqual(126, cout.Position); 425 cout.WriteSFixed32(501); 426 Assert.AreEqual(130, cout.Position); 427 cout.Flush(); 428 } 429 // Now test Input stream: 430 { 431 CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0, false); 432 Assert.AreEqual(0, cin.Position); 433 // Field 1: 434 uint tag = cin.ReadTag(); 435 Assert.AreEqual(1, tag >> 3); 436 Assert.AreEqual(1, cin.Position); 437 Assert.AreEqual(500, cin.ReadInt32()); 438 Assert.AreEqual(3, cin.Position); 439 //Field 2: 440 tag = cin.ReadTag(); 441 Assert.AreEqual(2, tag >> 3); 442 Assert.AreEqual(4, cin.Position); 443 int childlen = cin.ReadLength(); 444 Assert.AreEqual(120, childlen); 445 Assert.AreEqual(5, cin.Position); 446 int oldlimit = cin.PushLimit((int)childlen); 447 Assert.AreEqual(5, cin.Position); 448 // Now we are reading child message 449 { 450 // Field 11: numeric value: 500 451 tag = cin.ReadTag(); 452 Assert.AreEqual(11, tag >> 3); 453 Assert.AreEqual(6, cin.Position); 454 Assert.AreEqual(500, cin.ReadInt32()); 455 Assert.AreEqual(8, cin.Position); 456 //Field 12: length delimited 120 bytes 457 tag = cin.ReadTag(); 458 Assert.AreEqual(12, tag >> 3); 459 Assert.AreEqual(9, cin.Position); 460 ByteString bstr = cin.ReadBytes(); 461 Assert.AreEqual(110, bstr.Length); 462 Assert.AreEqual((byte) 109, bstr[109]); 463 Assert.AreEqual(120, cin.Position); 464 // Field 13: fixed numeric value: 501 465 tag = cin.ReadTag(); 466 Assert.AreEqual(13, tag >> 3); 467 // ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit 468 Assert.AreEqual(121, cin.Position); 469 Assert.AreEqual(501, cin.ReadSFixed32()); 470 Assert.AreEqual(125, cin.Position); 471 Assert.IsTrue(cin.IsAtEnd); 472 } 473 cin.PopLimit(oldlimit); 474 Assert.AreEqual(125, cin.Position); 475 // Field 3: fixed numeric value: 501 476 tag = cin.ReadTag(); 477 Assert.AreEqual(3, tag >> 3); 478 Assert.AreEqual(126, cin.Position); 479 Assert.AreEqual(501, cin.ReadSFixed32()); 480 Assert.AreEqual(130, cin.Position); 481 Assert.IsTrue(cin.IsAtEnd); 482 } 483 } 484 485 [Test] Dispose_DisposesUnderlyingStream()486 public void Dispose_DisposesUnderlyingStream() 487 { 488 var memoryStream = new MemoryStream(); 489 Assert.IsTrue(memoryStream.CanWrite); 490 using (var cos = new CodedOutputStream(memoryStream)) 491 { 492 cos.WriteRawBytes(new byte[] {0}); 493 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet 494 } 495 Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream 496 Assert.IsFalse(memoryStream.CanWrite); // Disposed 497 } 498 499 [Test] Dispose_WithLeaveOpen()500 public void Dispose_WithLeaveOpen() 501 { 502 var memoryStream = new MemoryStream(); 503 Assert.IsTrue(memoryStream.CanWrite); 504 using (var cos = new CodedOutputStream(memoryStream, true)) 505 { 506 cos.WriteRawBytes(new byte[] {0}); 507 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet 508 } 509 Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream 510 Assert.IsTrue(memoryStream.CanWrite); // We left the stream open 511 } 512 513 [Test] Dispose_FromByteArray()514 public void Dispose_FromByteArray() 515 { 516 var stream = new CodedOutputStream(new byte[10]); 517 stream.Dispose(); 518 } 519 } 520 }