| OLD | NEW |
| (Empty) |
| 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 NUnit.Framework; | |
| 37 | |
| 38 namespace Google.Protobuf | |
| 39 { | |
| 40 public class CodedOutputStreamTest | |
| 41 { | |
| 42 /// <summary> | |
| 43 /// Writes the given value using WriteRawVarint32() and WriteRawVarint64
() and | |
| 44 /// checks that the result matches the given bytes | |
| 45 /// </summary> | |
| 46 private static void AssertWriteVarint(byte[] data, ulong value) | |
| 47 { | |
| 48 // Only do 32-bit write if the value fits in 32 bits. | |
| 49 if ((value >> 32) == 0) | |
| 50 { | |
| 51 MemoryStream rawOutput = new MemoryStream(); | |
| 52 CodedOutputStream output = new CodedOutputStream(rawOutput); | |
| 53 output.WriteRawVarint32((uint) value); | |
| 54 output.Flush(); | |
| 55 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 56 // Also try computing size. | |
| 57 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint3
2Size((uint) value)); | |
| 58 } | |
| 59 | |
| 60 { | |
| 61 MemoryStream rawOutput = new MemoryStream(); | |
| 62 CodedOutputStream output = new CodedOutputStream(rawOutput); | |
| 63 output.WriteRawVarint64(value); | |
| 64 output.Flush(); | |
| 65 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 66 | |
| 67 // Also try computing size. | |
| 68 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint6
4Size(value)); | |
| 69 } | |
| 70 | |
| 71 // Try different buffer sizes. | |
| 72 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) | |
| 73 { | |
| 74 // Only do 32-bit write if the value fits in 32 bits. | |
| 75 if ((value >> 32) == 0) | |
| 76 { | |
| 77 MemoryStream rawOutput = new MemoryStream(); | |
| 78 CodedOutputStream output = | |
| 79 new CodedOutputStream(rawOutput, bufferSize); | |
| 80 output.WriteRawVarint32((uint) value); | |
| 81 output.Flush(); | |
| 82 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 83 } | |
| 84 | |
| 85 { | |
| 86 MemoryStream rawOutput = new MemoryStream(); | |
| 87 CodedOutputStream output = new CodedOutputStream(rawOutput,
bufferSize); | |
| 88 output.WriteRawVarint64(value); | |
| 89 output.Flush(); | |
| 90 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 91 } | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 /// <summary> | |
| 96 /// Tests WriteRawVarint32() and WriteRawVarint64() | |
| 97 /// </summary> | |
| 98 [Test] | |
| 99 public void WriteVarint() | |
| 100 { | |
| 101 AssertWriteVarint(new byte[] {0x00}, 0); | |
| 102 AssertWriteVarint(new byte[] {0x01}, 1); | |
| 103 AssertWriteVarint(new byte[] {0x7f}, 127); | |
| 104 // 14882 | |
| 105 AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7)
); | |
| 106 // 2961488830 | |
| 107 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b}, | |
| 108 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 <
< 21) | | |
| 109 (0x0bL << 28)); | |
| 110 | |
| 111 // 64-bit | |
| 112 // 7256456126 | |
| 113 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b}, | |
| 114 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 <
< 21) | | |
| 115 (0x1bL << 28)); | |
| 116 // 41256202580718336 | |
| 117 AssertWriteVarint( | |
| 118 new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, | |
| 119 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | | |
| 120 (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49)
); | |
| 121 // 11964378330978735131 | |
| 122 AssertWriteVarint( | |
| 123 new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6
, 0x01}, | |
| 124 unchecked((ulong) | |
| 125 ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 2
1) | | |
| 126 (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) | | |
| 127 (0x05L << 49) | (0x26L << 56) | (0x01L << 63)))); | |
| 128 } | |
| 129 | |
| 130 /// <summary> | |
| 131 /// Parses the given bytes using WriteRawLittleEndian32() and checks | |
| 132 /// that the result matches the given value. | |
| 133 /// </summary> | |
| 134 private static void AssertWriteLittleEndian32(byte[] data, uint value) | |
| 135 { | |
| 136 MemoryStream rawOutput = new MemoryStream(); | |
| 137 CodedOutputStream output = new CodedOutputStream(rawOutput); | |
| 138 output.WriteRawLittleEndian32(value); | |
| 139 output.Flush(); | |
| 140 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 141 | |
| 142 // Try different buffer sizes. | |
| 143 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) | |
| 144 { | |
| 145 rawOutput = new MemoryStream(); | |
| 146 output = new CodedOutputStream(rawOutput, bufferSize); | |
| 147 output.WriteRawLittleEndian32(value); | |
| 148 output.Flush(); | |
| 149 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 /// <summary> | |
| 154 /// Parses the given bytes using WriteRawLittleEndian64() and checks | |
| 155 /// that the result matches the given value. | |
| 156 /// </summary> | |
| 157 private static void AssertWriteLittleEndian64(byte[] data, ulong value) | |
| 158 { | |
| 159 MemoryStream rawOutput = new MemoryStream(); | |
| 160 CodedOutputStream output = new CodedOutputStream(rawOutput); | |
| 161 output.WriteRawLittleEndian64(value); | |
| 162 output.Flush(); | |
| 163 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 164 | |
| 165 // Try different block sizes. | |
| 166 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) | |
| 167 { | |
| 168 rawOutput = new MemoryStream(); | |
| 169 output = new CodedOutputStream(rawOutput, blockSize); | |
| 170 output.WriteRawLittleEndian64(value); | |
| 171 output.Flush(); | |
| 172 Assert.AreEqual(data, rawOutput.ToArray()); | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 /// <summary> | |
| 177 /// Tests writeRawLittleEndian32() and writeRawLittleEndian64(). | |
| 178 /// </summary> | |
| 179 [Test] | |
| 180 public void WriteLittleEndian() | |
| 181 { | |
| 182 AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x123
45678); | |
| 183 AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9ab
cdef0); | |
| 184 | |
| 185 AssertWriteLittleEndian64( | |
| 186 new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}, | |
| 187 0x123456789abcdef0L); | |
| 188 AssertWriteLittleEndian64( | |
| 189 new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a}, | |
| 190 0x9abcdef012345678UL); | |
| 191 } | |
| 192 | |
| 193 [Test] | |
| 194 public void WriteWholeMessage_VaryingBlockSizes() | |
| 195 { | |
| 196 TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); | |
| 197 | |
| 198 byte[] rawBytes = message.ToByteArray(); | |
| 199 | |
| 200 // Try different block sizes. | |
| 201 for (int blockSize = 1; blockSize < 256; blockSize *= 2) | |
| 202 { | |
| 203 MemoryStream rawOutput = new MemoryStream(); | |
| 204 CodedOutputStream output = new CodedOutputStream(rawOutput, bloc
kSize); | |
| 205 message.WriteTo(output); | |
| 206 output.Flush(); | |
| 207 Assert.AreEqual(rawBytes, rawOutput.ToArray()); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 [Test] | |
| 212 public void EncodeZigZag32() | |
| 213 { | |
| 214 Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); | |
| 215 Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); | |
| 216 Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); | |
| 217 Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); | |
| 218 Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFF
FFFF)); | |
| 219 Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchec
ked((int) 0xC0000000))); | |
| 220 Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFF
FFFF)); | |
| 221 Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchec
ked((int) 0x80000000))); | |
| 222 } | |
| 223 | |
| 224 [Test] | |
| 225 public void EncodeZigZag64() | |
| 226 { | |
| 227 Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); | |
| 228 Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); | |
| 229 Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); | |
| 230 Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); | |
| 231 Assert.AreEqual(0x000000007FFFFFFEuL, | |
| 232 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
000000003FFFFFFFUL))); | |
| 233 Assert.AreEqual(0x000000007FFFFFFFuL, | |
| 234 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
FFFFFFFFC0000000UL))); | |
| 235 Assert.AreEqual(0x00000000FFFFFFFEuL, | |
| 236 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
000000007FFFFFFFUL))); | |
| 237 Assert.AreEqual(0x00000000FFFFFFFFuL, | |
| 238 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
FFFFFFFF80000000UL))); | |
| 239 Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, | |
| 240 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
7FFFFFFFFFFFFFFFUL))); | |
| 241 Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, | |
| 242 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x
8000000000000000UL))); | |
| 243 } | |
| 244 | |
| 245 [Test] | |
| 246 public void RoundTripZigZag32() | |
| 247 { | |
| 248 // Some easier-to-verify round-trip tests. The inputs (other than 0
, 1, -1) | |
| 249 // were chosen semi-randomly via keyboard bashing. | |
| 250 Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream
.EncodeZigZag32(0))); | |
| 251 Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream
.EncodeZigZag32(1))); | |
| 252 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStrea
m.EncodeZigZag32(-1))); | |
| 253 Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputSt
ream.EncodeZigZag32(14927))); | |
| 254 Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputSt
ream.EncodeZigZag32(-3612))); | |
| 255 } | |
| 256 | |
| 257 [Test] | |
| 258 public void RoundTripZigZag64() | |
| 259 { | |
| 260 Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream
.EncodeZigZag64(0))); | |
| 261 Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream
.EncodeZigZag64(1))); | |
| 262 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStrea
m.EncodeZigZag64(-1))); | |
| 263 Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputSt
ream.EncodeZigZag64(14927))); | |
| 264 Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputSt
ream.EncodeZigZag64(-3612))); | |
| 265 | |
| 266 Assert.AreEqual(856912304801416L, | |
| 267 CodedInputStream.DecodeZigZag64(CodedOutputStream.En
codeZigZag64(856912304801416L))); | |
| 268 Assert.AreEqual(-75123905439571256L, | |
| 269 CodedInputStream.DecodeZigZag64(CodedOutputStream.En
codeZigZag64(-75123905439571256L))); | |
| 270 } | |
| 271 | |
| 272 [Test] | |
| 273 public void TestNegativeEnumNoTag() | |
| 274 { | |
| 275 Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2)); | |
| 276 Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEn
um.NegativeValue)); | |
| 277 | |
| 278 byte[] bytes = new byte[10]; | |
| 279 CodedOutputStream output = new CodedOutputStream(bytes); | |
| 280 output.WriteEnum((int) SampleEnum.NegativeValue); | |
| 281 | |
| 282 Assert.AreEqual(0, output.SpaceLeft); | |
| 283 Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToStri
ng(bytes)); | |
| 284 } | |
| 285 | |
| 286 [Test] | |
| 287 public void TestCodedInputOutputPosition() | |
| 288 { | |
| 289 byte[] content = new byte[110]; | |
| 290 for (int i = 0; i < content.Length; i++) | |
| 291 content[i] = (byte)i; | |
| 292 | |
| 293 byte[] child = new byte[120]; | |
| 294 { | |
| 295 MemoryStream ms = new MemoryStream(child); | |
| 296 CodedOutputStream cout = new CodedOutputStream(ms, 20); | |
| 297 // Field 11: numeric value: 500 | |
| 298 cout.WriteTag(11, WireFormat.WireType.Varint); | |
| 299 Assert.AreEqual(1, cout.Position); | |
| 300 cout.WriteInt32(500); | |
| 301 Assert.AreEqual(3, cout.Position); | |
| 302 //Field 12: length delimited 120 bytes | |
| 303 cout.WriteTag(12, WireFormat.WireType.LengthDelimited); | |
| 304 Assert.AreEqual(4, cout.Position); | |
| 305 cout.WriteBytes(ByteString.CopyFrom(content)); | |
| 306 Assert.AreEqual(115, cout.Position); | |
| 307 // Field 13: fixed numeric value: 501 | |
| 308 cout.WriteTag(13, WireFormat.WireType.Fixed32); | |
| 309 Assert.AreEqual(116, cout.Position); | |
| 310 cout.WriteSFixed32(501); | |
| 311 Assert.AreEqual(120, cout.Position); | |
| 312 cout.Flush(); | |
| 313 } | |
| 314 | |
| 315 byte[] bytes = new byte[130]; | |
| 316 { | |
| 317 CodedOutputStream cout = new CodedOutputStream(bytes); | |
| 318 // Field 1: numeric value: 500 | |
| 319 cout.WriteTag(1, WireFormat.WireType.Varint); | |
| 320 Assert.AreEqual(1, cout.Position); | |
| 321 cout.WriteInt32(500); | |
| 322 Assert.AreEqual(3, cout.Position); | |
| 323 //Field 2: length delimited 120 bytes | |
| 324 cout.WriteTag(2, WireFormat.WireType.LengthDelimited); | |
| 325 Assert.AreEqual(4, cout.Position); | |
| 326 cout.WriteBytes(ByteString.CopyFrom(child)); | |
| 327 Assert.AreEqual(125, cout.Position); | |
| 328 // Field 3: fixed numeric value: 500 | |
| 329 cout.WriteTag(3, WireFormat.WireType.Fixed32); | |
| 330 Assert.AreEqual(126, cout.Position); | |
| 331 cout.WriteSFixed32(501); | |
| 332 Assert.AreEqual(130, cout.Position); | |
| 333 cout.Flush(); | |
| 334 } | |
| 335 // Now test Input stream: | |
| 336 { | |
| 337 CodedInputStream cin = new CodedInputStream(new MemoryStream(byt
es), new byte[50], 0, 0); | |
| 338 Assert.AreEqual(0, cin.Position); | |
| 339 // Field 1: | |
| 340 uint tag = cin.ReadTag(); | |
| 341 Assert.AreEqual(1, tag >> 3); | |
| 342 Assert.AreEqual(1, cin.Position); | |
| 343 Assert.AreEqual(500, cin.ReadInt32()); | |
| 344 Assert.AreEqual(3, cin.Position); | |
| 345 //Field 2: | |
| 346 tag = cin.ReadTag(); | |
| 347 Assert.AreEqual(2, tag >> 3); | |
| 348 Assert.AreEqual(4, cin.Position); | |
| 349 int childlen = cin.ReadLength(); | |
| 350 Assert.AreEqual(120, childlen); | |
| 351 Assert.AreEqual(5, cin.Position); | |
| 352 int oldlimit = cin.PushLimit((int)childlen); | |
| 353 Assert.AreEqual(5, cin.Position); | |
| 354 // Now we are reading child message | |
| 355 { | |
| 356 // Field 11: numeric value: 500 | |
| 357 tag = cin.ReadTag(); | |
| 358 Assert.AreEqual(11, tag >> 3); | |
| 359 Assert.AreEqual(6, cin.Position); | |
| 360 Assert.AreEqual(500, cin.ReadInt32()); | |
| 361 Assert.AreEqual(8, cin.Position); | |
| 362 //Field 12: length delimited 120 bytes | |
| 363 tag = cin.ReadTag(); | |
| 364 Assert.AreEqual(12, tag >> 3); | |
| 365 Assert.AreEqual(9, cin.Position); | |
| 366 ByteString bstr = cin.ReadBytes(); | |
| 367 Assert.AreEqual(110, bstr.Length); | |
| 368 Assert.AreEqual((byte) 109, bstr[109]); | |
| 369 Assert.AreEqual(120, cin.Position); | |
| 370 // Field 13: fixed numeric value: 501 | |
| 371 tag = cin.ReadTag(); | |
| 372 Assert.AreEqual(13, tag >> 3); | |
| 373 // ROK - Previously broken here, this returned 126 failing t
o account for bufferSizeAfterLimit | |
| 374 Assert.AreEqual(121, cin.Position); | |
| 375 Assert.AreEqual(501, cin.ReadSFixed32()); | |
| 376 Assert.AreEqual(125, cin.Position); | |
| 377 Assert.IsTrue(cin.IsAtEnd); | |
| 378 } | |
| 379 cin.PopLimit(oldlimit); | |
| 380 Assert.AreEqual(125, cin.Position); | |
| 381 // Field 3: fixed numeric value: 501 | |
| 382 tag = cin.ReadTag(); | |
| 383 Assert.AreEqual(3, tag >> 3); | |
| 384 Assert.AreEqual(126, cin.Position); | |
| 385 Assert.AreEqual(501, cin.ReadSFixed32()); | |
| 386 Assert.AreEqual(130, cin.Position); | |
| 387 Assert.IsTrue(cin.IsAtEnd); | |
| 388 } | |
| 389 } | |
| 390 } | |
| 391 } | |
| OLD | NEW |