blob: d041d3f0ddcd691d5e34949b85d3396a74f8fa6a [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
csharptesta105eac2011-09-09 13:39:54 -050037using System;
38using System.Collections.Generic;
csharptest71f662c2011-05-20 15:15:34 -050039using System.IO;
40using Google.ProtocolBuffers.TestProtos;
41using NUnit.Framework;
42
43namespace Google.ProtocolBuffers
44{
45 [TestFixture]
46 public class CodedOutputStreamTest
47 {
48 /// <summary>
49 /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
50 /// checks that the result matches the given bytes
51 /// </summary>
52 private static void AssertWriteVarint(byte[] data, ulong value)
53 {
54 // Only do 32-bit write if the value fits in 32 bits.
55 if ((value >> 32) == 0)
56 {
57 MemoryStream rawOutput = new MemoryStream();
58 CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
59 output.WriteRawVarint32((uint) value);
60 output.Flush();
61 Assert.AreEqual(data, rawOutput.ToArray());
62 // Also try computing size.
63 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
64 }
65
66 {
67 MemoryStream rawOutput = new MemoryStream();
68 CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
69 output.WriteRawVarint64(value);
70 output.Flush();
71 Assert.AreEqual(data, rawOutput.ToArray());
72
73 // Also try computing size.
74 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
75 }
76
77 // Try different buffer sizes.
78 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
79 {
80 // Only do 32-bit write if the value fits in 32 bits.
81 if ((value >> 32) == 0)
82 {
83 MemoryStream rawOutput = new MemoryStream();
84 CodedOutputStream output =
85 CodedOutputStream.CreateInstance(rawOutput, bufferSize);
86 output.WriteRawVarint32((uint) value);
87 output.Flush();
88 Assert.AreEqual(data, rawOutput.ToArray());
89 }
90
91 {
92 MemoryStream rawOutput = new MemoryStream();
93 CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
94 output.WriteRawVarint64(value);
95 output.Flush();
96 Assert.AreEqual(data, rawOutput.ToArray());
97 }
98 }
99 }
100
101 /// <summary>
102 /// Tests WriteRawVarint32() and WriteRawVarint64()
103 /// </summary>
104 [Test]
105 public void WriteVarint()
106 {
107 AssertWriteVarint(new byte[] {0x00}, 0);
108 AssertWriteVarint(new byte[] {0x01}, 1);
109 AssertWriteVarint(new byte[] {0x7f}, 127);
110 // 14882
111 AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
112 // 2961488830
113 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
114 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
115 (0x0bL << 28));
116
117 // 64-bit
118 // 7256456126
119 AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
120 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
121 (0x1bL << 28));
122 // 41256202580718336
123 AssertWriteVarint(
124 new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
125 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
126 (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
127 // 11964378330978735131
128 AssertWriteVarint(
129 new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
130 unchecked((ulong)
131 ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
132 (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
133 (0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
134 }
135
136 /// <summary>
137 /// Parses the given bytes using WriteRawLittleEndian32() and checks
138 /// that the result matches the given value.
139 /// </summary>
140 private static void AssertWriteLittleEndian32(byte[] data, uint value)
141 {
142 MemoryStream rawOutput = new MemoryStream();
143 CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
144 output.WriteRawLittleEndian32(value);
145 output.Flush();
146 Assert.AreEqual(data, rawOutput.ToArray());
147
148 // Try different buffer sizes.
149 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
150 {
151 rawOutput = new MemoryStream();
152 output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
153 output.WriteRawLittleEndian32(value);
154 output.Flush();
155 Assert.AreEqual(data, rawOutput.ToArray());
156 }
157 }
158
159 /// <summary>
160 /// Parses the given bytes using WriteRawLittleEndian64() and checks
161 /// that the result matches the given value.
162 /// </summary>
163 private static void AssertWriteLittleEndian64(byte[] data, ulong value)
164 {
165 MemoryStream rawOutput = new MemoryStream();
166 CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
167 output.WriteRawLittleEndian64(value);
168 output.Flush();
169 Assert.AreEqual(data, rawOutput.ToArray());
170
171 // Try different block sizes.
172 for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
173 {
174 rawOutput = new MemoryStream();
175 output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
176 output.WriteRawLittleEndian64(value);
177 output.Flush();
178 Assert.AreEqual(data, rawOutput.ToArray());
179 }
180 }
181
182 /// <summary>
183 /// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
184 /// </summary>
185 [Test]
186 public void WriteLittleEndian()
187 {
188 AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
189 AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
190
191 AssertWriteLittleEndian64(
192 new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
193 0x123456789abcdef0L);
194 AssertWriteLittleEndian64(
195 new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
196 0x9abcdef012345678UL);
197 }
198
199 [Test]
200 public void WriteWholeMessage()
201 {
202 TestAllTypes message = TestUtil.GetAllSet();
203
204 byte[] rawBytes = message.ToByteArray();
205 TestUtil.AssertEqualBytes(TestUtil.GoldenMessage.ToByteArray(), rawBytes);
206
207 // Try different block sizes.
208 for (int blockSize = 1; blockSize < 256; blockSize *= 2)
209 {
210 MemoryStream rawOutput = new MemoryStream();
211 CodedOutputStream output =
212 CodedOutputStream.CreateInstance(rawOutput, blockSize);
213 message.WriteTo(output);
214 output.Flush();
215 TestUtil.AssertEqualBytes(rawBytes, rawOutput.ToArray());
216 }
217 }
218
219 /// <summary>
220 /// Tests writing a whole message with every packed field type. Ensures the
221 /// wire format of packed fields is compatible with C++.
222 /// </summary>
223 [Test]
224 public void WriteWholePackedFieldsMessage()
225 {
226 TestPackedTypes message = TestUtil.GetPackedSet();
227
228 byte[] rawBytes = message.ToByteArray();
229 TestUtil.AssertEqualBytes(TestUtil.GetGoldenPackedFieldsMessage().ToByteArray(),
230 rawBytes);
231 }
232
233 [Test]
234 public void EncodeZigZag32()
235 {
236 Assert.AreEqual(0, CodedOutputStream.EncodeZigZag32(0));
237 Assert.AreEqual(1, CodedOutputStream.EncodeZigZag32(-1));
238 Assert.AreEqual(2, CodedOutputStream.EncodeZigZag32(1));
239 Assert.AreEqual(3, CodedOutputStream.EncodeZigZag32(-2));
240 Assert.AreEqual(0x7FFFFFFE, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
241 Assert.AreEqual(0x7FFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));
242 Assert.AreEqual(0xFFFFFFFE, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
243 Assert.AreEqual(0xFFFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));
244 }
245
246 [Test]
247 public void EncodeZigZag64()
248 {
249 Assert.AreEqual(0, CodedOutputStream.EncodeZigZag64(0));
250 Assert.AreEqual(1, CodedOutputStream.EncodeZigZag64(-1));
251 Assert.AreEqual(2, CodedOutputStream.EncodeZigZag64(1));
252 Assert.AreEqual(3, CodedOutputStream.EncodeZigZag64(-2));
253 Assert.AreEqual(0x000000007FFFFFFEL,
254 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
255 Assert.AreEqual(0x000000007FFFFFFFL,
256 CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
257 Assert.AreEqual(0x00000000FFFFFFFEL,
258 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
259 Assert.AreEqual(0x00000000FFFFFFFFL,
260 CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
261 Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
262 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
263 Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
264 CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
265 }
266
267 [Test]
268 public void RoundTripZigZag32()
269 {
270 // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
271 // were chosen semi-randomly via keyboard bashing.
272 Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
273 Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
274 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
275 Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
276 Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
277 }
278
279 [Test]
280 public void RoundTripZigZag64()
281 {
282 Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
283 Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
284 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
285 Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
286 Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
287
288 Assert.AreEqual(856912304801416L,
289 CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
290 Assert.AreEqual(-75123905439571256L,
291 CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
292 }
csharptesta105eac2011-09-09 13:39:54 -0500293
294 [Test]
295 public void TestNegativeEnumNoTag()
296 {
297 Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2));
298 Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(-2));
299
300 byte[] bytes = new byte[10];
301 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
302 output.WriteEnumNoTag(-2);
303
304 Assert.AreEqual(0, output.SpaceLeft);
305 Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
306 }
307
308 [Test]
309 public void TestNegativeEnumWithTag()
310 {
311 Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2));
312 Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, -2));
313
314 byte[] bytes = new byte[11];
315 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
316 output.WriteEnum(8, "", -2, -2);
317
318 Assert.AreEqual(0, output.SpaceLeft);
319 //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift
320 Assert.AreEqual("40-FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
321 }
322
323 [Test]
324 public void TestNegativeEnumArrayPacked()
325 {
326 int arraySize = 1 + (10 * 5);
327 int msgSize = 1 + 1 + arraySize;
328 byte[] bytes = new byte[msgSize];
329 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
330 output.WritePackedEnumArray(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
331
332 Assert.AreEqual(0, output.SpaceLeft);
333
334 CodedInputStream input = CodedInputStream.CreateInstance(bytes);
335 uint tag;
336 string name;
337 Assert.IsTrue(input.ReadTag(out tag, out name));
338
339 List<int> values = new List<int>();
340 input.ReadInt32Array(tag, name, values);
341
342 Assert.AreEqual(6, values.Count);
343 for (int i = 0; i > -6; i--)
344 Assert.AreEqual(i, values[Math.Abs(i)]);
345 }
346
347 [Test]
348 public void TestNegativeEnumArray()
349 {
350 int arraySize = 1 + 1 + (11 * 5);
351 int msgSize = arraySize;
352 byte[] bytes = new byte[msgSize];
353 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
354 output.WriteEnumArray(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
355
356 Assert.AreEqual(0, output.SpaceLeft);
357
358 CodedInputStream input = CodedInputStream.CreateInstance(bytes);
359 uint tag;
360 string name;
361 Assert.IsTrue(input.ReadTag(out tag, out name));
362
363 List<int> values = new List<int>();
364 input.ReadInt32Array(tag, name, values);
365
366 Assert.AreEqual(6, values.Count);
367 for (int i = 0; i > -6; i--)
368 Assert.AreEqual(i, values[Math.Abs(i)]);
369 }
csharptest71f662c2011-05-20 15:15:34 -0500370 }
371}