CodedOutputStreamTest.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System.IO;
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc.
  4. // http://code.google.com/p/protobuf/
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License");
  7. // you may not use this file except in compliance with the License.
  8. // You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. using Google.ProtocolBuffers.TestProtos;
  18. using NUnit.Framework;
  19. namespace Google.ProtocolBuffers {
  20. [TestFixture]
  21. public class CodedOutputStreamTest {
  22. /// <summary>
  23. /// Helper to construct a byte array from a bunch of bytes. The inputs are
  24. /// actually ints so that I can use hex notation and not get stupid errors
  25. /// about precision.
  26. /// </summary>
  27. private static byte[] Bytes(params int[] bytesAsInts) {
  28. byte[] bytes = new byte[bytesAsInts.Length];
  29. for (int i = 0; i < bytesAsInts.Length; i++) {
  30. bytes[i] = (byte) bytesAsInts[i];
  31. }
  32. return bytes;
  33. }
  34. private static void AssertEqualBytes(byte[] a, byte[] b) {
  35. Assert.AreEqual(ByteString.CopyFrom(a), ByteString.CopyFrom(b));
  36. }
  37. /// <summary>
  38. /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
  39. /// checks that the result matches the given bytes
  40. /// </summary>
  41. private static void AssertWriteVarint(byte[] data, ulong value) {
  42. // Only do 32-bit write if the value fits in 32 bits.
  43. if ((value >> 32) == 0) {
  44. MemoryStream rawOutput = new MemoryStream();
  45. CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
  46. output.WriteRawVarint32((uint) value);
  47. output.Flush();
  48. Assert.AreEqual(data, rawOutput.ToArray());
  49. // Also try computing size.
  50. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
  51. }
  52. {
  53. MemoryStream rawOutput = new MemoryStream();
  54. CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
  55. output.WriteRawVarint64(value);
  56. output.Flush();
  57. Assert.AreEqual(data, rawOutput.ToArray());
  58. // Also try computing size.
  59. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
  60. }
  61. // Try different buffer sizes.
  62. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
  63. // Only do 32-bit write if the value fits in 32 bits.
  64. if ((value >> 32) == 0) {
  65. MemoryStream rawOutput = new MemoryStream();
  66. CodedOutputStream output =
  67. CodedOutputStream.CreateInstance(rawOutput, bufferSize);
  68. output.WriteRawVarint32((uint) value);
  69. output.Flush();
  70. Assert.AreEqual(data, rawOutput.ToArray());
  71. }
  72. {
  73. MemoryStream rawOutput = new MemoryStream();
  74. CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
  75. output.WriteRawVarint64(value);
  76. output.Flush();
  77. Assert.AreEqual(data, rawOutput.ToArray());
  78. }
  79. }
  80. }
  81. /// <summary>
  82. /// Tests WriteRawVarint32() and WriteRawVarint64()
  83. /// </summary>
  84. [Test]
  85. public void WriteVarint() {
  86. AssertWriteVarint(Bytes(0x00), 0);
  87. AssertWriteVarint(Bytes(0x01), 1);
  88. AssertWriteVarint(Bytes(0x7f), 127);
  89. // 14882
  90. AssertWriteVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
  91. // 2961488830
  92. AssertWriteVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
  93. (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
  94. (0x0bL << 28));
  95. // 64-bit
  96. // 7256456126
  97. AssertWriteVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
  98. (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
  99. (0x1bL << 28));
  100. // 41256202580718336
  101. AssertWriteVarint(
  102. Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
  103. (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
  104. (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
  105. // 11964378330978735131
  106. AssertWriteVarint(
  107. Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
  108. unchecked((ulong)
  109. ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
  110. (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
  111. (0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
  112. }
  113. /// <summary>
  114. /// Parses the given bytes using WriteRawLittleEndian32() and checks
  115. /// that the result matches the given value.
  116. /// </summary>
  117. private static void AssertWriteLittleEndian32(byte[] data, uint value) {
  118. MemoryStream rawOutput = new MemoryStream();
  119. CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
  120. output.WriteRawLittleEndian32(value);
  121. output.Flush();
  122. Assert.AreEqual(data, rawOutput.ToArray());
  123. // Try different buffer sizes.
  124. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
  125. rawOutput = new MemoryStream();
  126. output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
  127. output.WriteRawLittleEndian32(value);
  128. output.Flush();
  129. Assert.AreEqual(data, rawOutput.ToArray());
  130. }
  131. }
  132. /// <summary>
  133. /// Parses the given bytes using WriteRawLittleEndian64() and checks
  134. /// that the result matches the given value.
  135. /// </summary>
  136. private static void AssertWriteLittleEndian64(byte[] data, ulong value) {
  137. MemoryStream rawOutput = new MemoryStream();
  138. CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
  139. output.WriteRawLittleEndian64(value);
  140. output.Flush();
  141. Assert.AreEqual(data, rawOutput.ToArray());
  142. // Try different block sizes.
  143. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
  144. rawOutput = new MemoryStream();
  145. output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
  146. output.WriteRawLittleEndian64(value);
  147. output.Flush();
  148. Assert.AreEqual(data, rawOutput.ToArray());
  149. }
  150. }
  151. /// <summary>
  152. /// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
  153. /// </summary>
  154. [Test]
  155. public void WriteLittleEndian() {
  156. AssertWriteLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
  157. AssertWriteLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
  158. AssertWriteLittleEndian64(
  159. Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
  160. 0x123456789abcdef0L);
  161. AssertWriteLittleEndian64(
  162. Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
  163. 0x9abcdef012345678UL);
  164. }
  165. [Test]
  166. public void WriteWholeMessage() {
  167. TestAllTypes message = TestUtil.GetAllSet();
  168. byte[] rawBytes = message.ToByteArray();
  169. AssertEqualBytes(TestUtil.GoldenMessage.ToByteArray(), rawBytes);
  170. // Try different block sizes.
  171. for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
  172. MemoryStream rawOutput = new MemoryStream();
  173. CodedOutputStream output =
  174. CodedOutputStream.CreateInstance(rawOutput, blockSize);
  175. message.WriteTo(output);
  176. output.Flush();
  177. AssertEqualBytes(rawBytes, rawOutput.ToArray());
  178. }
  179. }
  180. [Test]
  181. public void EncodeZigZag32() {
  182. Assert.AreEqual(0, CodedOutputStream.EncodeZigZag32( 0));
  183. Assert.AreEqual(1, CodedOutputStream.EncodeZigZag32(-1));
  184. Assert.AreEqual(2, CodedOutputStream.EncodeZigZag32( 1));
  185. Assert.AreEqual(3, CodedOutputStream.EncodeZigZag32(-2));
  186. Assert.AreEqual(0x7FFFFFFE, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
  187. Assert.AreEqual(0x7FFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0xC0000000)));
  188. Assert.AreEqual(0xFFFFFFFE, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
  189. Assert.AreEqual(0xFFFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0x80000000)));
  190. }
  191. [Test]
  192. public void EncodeZigZag64() {
  193. Assert.AreEqual(0, CodedOutputStream.EncodeZigZag64( 0));
  194. Assert.AreEqual(1, CodedOutputStream.EncodeZigZag64(-1));
  195. Assert.AreEqual(2, CodedOutputStream.EncodeZigZag64( 1));
  196. Assert.AreEqual(3, CodedOutputStream.EncodeZigZag64(-2));
  197. Assert.AreEqual(0x000000007FFFFFFEL,
  198. CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000003FFFFFFFUL)));
  199. Assert.AreEqual(0x000000007FFFFFFFL,
  200. CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFFC0000000UL)));
  201. Assert.AreEqual(0x00000000FFFFFFFEL,
  202. CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000007FFFFFFFUL)));
  203. Assert.AreEqual(0x00000000FFFFFFFFL,
  204. CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFF80000000UL)));
  205. Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
  206. CodedOutputStream.EncodeZigZag64(unchecked((long)0x7FFFFFFFFFFFFFFFUL)));
  207. Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
  208. CodedOutputStream.EncodeZigZag64(unchecked((long)0x8000000000000000UL)));
  209. }
  210. [Test]
  211. public void RoundTripZigZag32() {
  212. // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
  213. // were chosen semi-randomly via keyboard bashing.
  214. Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
  215. Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
  216. Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
  217. Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
  218. Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
  219. }
  220. [Test]
  221. public void RoundTripZigZag64() {
  222. Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
  223. Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
  224. Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
  225. Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
  226. Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
  227. Assert.AreEqual(856912304801416L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
  228. Assert.AreEqual(-75123905439571256L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
  229. }
  230. }
  231. }