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 |