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