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 |