blob: 64656b196f779851a77d8c0d8d0a3248fc2a75b7 [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
37using System;
csharptesta105eac2011-09-09 13:39:54 -050038using System.Collections.Generic;
csharptest71f662c2011-05-20 15:15:34 -050039using System.IO;
40using Google.ProtocolBuffers.TestProtos;
41using NUnit.Framework;
42using System.Diagnostics;
43
44namespace Google.ProtocolBuffers
45{
46 [TestFixture]
47 public class CodedInputStreamTest
48 {
49 /// <summary>
50 /// Helper to construct a byte array from a bunch of bytes. The inputs are
51 /// actually ints so that I can use hex notation and not get stupid errors
52 /// about precision.
53 /// </summary>
54 private static byte[] Bytes(params int[] bytesAsInts)
55 {
56 byte[] bytes = new byte[bytesAsInts.Length];
57 for (int i = 0; i < bytesAsInts.Length; i++)
58 {
59 bytes[i] = (byte) bytesAsInts[i];
60 }
61 return bytes;
62 }
63
64 /// <summary>
65 /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
66 /// </summary>
67 private static void AssertReadVarint(byte[] data, ulong value)
68 {
69 CodedInputStream input = CodedInputStream.CreateInstance(data);
70 Assert.AreEqual((uint) value, input.ReadRawVarint32());
71
72 input = CodedInputStream.CreateInstance(data);
73 Assert.AreEqual(value, input.ReadRawVarint64());
74 Assert.IsTrue(input.IsAtEnd);
75
76 // Try different block sizes.
77 for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
78 {
79 input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
80 Assert.AreEqual((uint) value, input.ReadRawVarint32());
81
82 input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
83 Assert.AreEqual(value, input.ReadRawVarint64());
84 Assert.IsTrue(input.IsAtEnd);
85 }
86
87 // Try reading directly from a MemoryStream. We want to verify that it
88 // doesn't read past the end of the input, so write an extra byte - this
89 // lets us test the position at the end.
90 MemoryStream memoryStream = new MemoryStream();
91 memoryStream.Write(data, 0, data.Length);
92 memoryStream.WriteByte(0);
93 memoryStream.Position = 0;
94 Assert.AreEqual((uint) value, CodedInputStream.ReadRawVarint32(memoryStream));
95 Assert.AreEqual(data.Length, memoryStream.Position);
96 }
97
98 /// <summary>
99 /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
100 /// expects them to fail with an InvalidProtocolBufferException whose
101 /// description matches the given one.
102 /// </summary>
103 private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
104 {
105 CodedInputStream input = CodedInputStream.CreateInstance(data);
106 try
107 {
108 input.ReadRawVarint32();
109 Assert.Fail("Should have thrown an exception.");
110 }
111 catch (InvalidProtocolBufferException e)
112 {
113 Assert.AreEqual(expected.Message, e.Message);
114 }
115
116 input = CodedInputStream.CreateInstance(data);
117 try
118 {
119 input.ReadRawVarint64();
120 Assert.Fail("Should have thrown an exception.");
121 }
122 catch (InvalidProtocolBufferException e)
123 {
124 Assert.AreEqual(expected.Message, e.Message);
125 }
126
127 // Make sure we get the same error when reading directly from a Stream.
128 try
129 {
130 CodedInputStream.ReadRawVarint32(new MemoryStream(data));
131 Assert.Fail("Should have thrown an exception.");
132 }
133 catch (InvalidProtocolBufferException e)
134 {
135 Assert.AreEqual(expected.Message, e.Message);
136 }
137 }
138
139 [Test]
140 public void ReadVarint()
141 {
142 AssertReadVarint(Bytes(0x00), 0);
143 AssertReadVarint(Bytes(0x01), 1);
144 AssertReadVarint(Bytes(0x7f), 127);
145 // 14882
146 AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
147 // 2961488830
148 AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
149 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
150 (0x0bL << 28));
151
152 // 64-bit
153 // 7256456126
154 AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
155 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
156 (0x1bL << 28));
157 // 41256202580718336
158 AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
159 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
160 (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
161 // 11964378330978735131
162 AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
163 (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
164 (0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
165 (0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));
166
167 // Failures
168 AssertReadVarintFailure(
169 InvalidProtocolBufferException.MalformedVarint(),
170 Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
171 0x00));
172 AssertReadVarintFailure(
173 InvalidProtocolBufferException.TruncatedMessage(),
174 Bytes(0x80));
175 }
176
177 /// <summary>
178 /// Parses the given bytes using ReadRawLittleEndian32() and checks
179 /// that the result matches the given value.
180 /// </summary>
181 private static void AssertReadLittleEndian32(byte[] data, uint value)
182 {
183 CodedInputStream input = CodedInputStream.CreateInstance(data);
184 Assert.AreEqual(value, input.ReadRawLittleEndian32());
185 Assert.IsTrue(input.IsAtEnd);
186
187 // Try different block sizes.
188 for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
189 {
190 input = CodedInputStream.CreateInstance(
191 new SmallBlockInputStream(data, blockSize));
192 Assert.AreEqual(value, input.ReadRawLittleEndian32());
193 Assert.IsTrue(input.IsAtEnd);
194 }
195 }
196
197 /// <summary>
198 /// Parses the given bytes using ReadRawLittleEndian64() and checks
199 /// that the result matches the given value.
200 /// </summary>
201 private static void AssertReadLittleEndian64(byte[] data, ulong value)
202 {
203 CodedInputStream input = CodedInputStream.CreateInstance(data);
204 Assert.AreEqual(value, input.ReadRawLittleEndian64());
205 Assert.IsTrue(input.IsAtEnd);
206
207 // Try different block sizes.
208 for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
209 {
210 input = CodedInputStream.CreateInstance(
211 new SmallBlockInputStream(data, blockSize));
212 Assert.AreEqual(value, input.ReadRawLittleEndian64());
213 Assert.IsTrue(input.IsAtEnd);
214 }
215 }
216
217 [Test]
218 public void ReadLittleEndian()
219 {
220 AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
221 AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
222
223 AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
224 0x123456789abcdef0L);
225 AssertReadLittleEndian64(
226 Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
227 }
228
229 [Test]
230 public void DecodeZigZag32()
231 {
232 Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));
233 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
234 Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));
235 Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
236 Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
237 Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
238 Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
239 Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
240 }
241
242 [Test]
243 public void DecodeZigZag64()
244 {
245 Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));
246 Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
247 Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));
248 Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
249 Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
250 Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
251 Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
252 Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
253 Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
254 Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
255 }
256
257 [Test]
258 public void ReadWholeMessage()
259 {
260 TestAllTypes message = TestUtil.GetAllSet();
261
262 byte[] rawBytes = message.ToByteArray();
263 Assert.AreEqual(rawBytes.Length, message.SerializedSize);
264 TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
265 TestUtil.AssertAllFieldsSet(message2);
266
267 // Try different block sizes.
268 for (int blockSize = 1; blockSize < 256; blockSize *= 2)
269 {
270 message2 = TestAllTypes.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
271 TestUtil.AssertAllFieldsSet(message2);
272 }
273 }
274
275 [Test]
276 public void SkipWholeMessage()
277 {
278 TestAllTypes message = TestUtil.GetAllSet();
279 byte[] rawBytes = message.ToByteArray();
280
281 // Create two parallel inputs. Parse one as unknown fields while using
282 // skipField() to skip each field on the other. Expect the same tags.
283 CodedInputStream input1 = CodedInputStream.CreateInstance(rawBytes);
284 CodedInputStream input2 = CodedInputStream.CreateInstance(rawBytes);
285 UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder();
286
csharptest123e5342011-06-03 14:15:21 -0500287 uint tag;
288 string name;
289 while (input1.ReadTag(out tag, out name))
csharptest71f662c2011-05-20 15:15:34 -0500290 {
csharptest123e5342011-06-03 14:15:21 -0500291 uint tag2;
292 Assert.IsTrue(input2.ReadTag(out tag2, out name));
293 Assert.AreEqual(tag, tag2);
294
csharptest71f662c2011-05-20 15:15:34 -0500295 unknownFields.MergeFieldFrom(tag, input1);
csharptest123e5342011-06-03 14:15:21 -0500296 input2.SkipField();
csharptest71f662c2011-05-20 15:15:34 -0500297 }
298 }
299
300 /// <summary>
301 /// Test that a bug in SkipRawBytes has been fixed: if the skip
302 /// skips exactly up to a limit, this should bnot break things
303 /// </summary>
304 [Test]
305 public void SkipRawBytesBug()
306 {
307 byte[] rawBytes = new byte[] {1, 2};
308 CodedInputStream input = CodedInputStream.CreateInstance(rawBytes);
309
310 int limit = input.PushLimit(1);
311 input.SkipRawBytes(1);
312 input.PopLimit(limit);
313 Assert.AreEqual(2, input.ReadRawByte());
314 }
315
316 public void ReadHugeBlob()
317 {
318 // Allocate and initialize a 1MB blob.
319 byte[] blob = new byte[1 << 20];
320 for (int i = 0; i < blob.Length; i++)
321 {
322 blob[i] = (byte) i;
323 }
324
325 // Make a message containing it.
326 TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
327 TestUtil.SetAllFields(builder);
328 builder.SetOptionalBytes(ByteString.CopyFrom(blob));
329 TestAllTypes message = builder.Build();
330
331 // Serialize and parse it. Make sure to parse from an InputStream, not
332 // directly from a ByteString, so that CodedInputStream uses buffered
333 // reading.
334 TestAllTypes message2 = TestAllTypes.ParseFrom(message.ToByteString().CreateCodedInput());
335
336 Assert.AreEqual(message.OptionalBytes, message2.OptionalBytes);
337
338 // Make sure all the other fields were parsed correctly.
339 TestAllTypes message3 = TestAllTypes.CreateBuilder(message2)
340 .SetOptionalBytes(TestUtil.GetAllSet().OptionalBytes)
341 .Build();
342 TestUtil.AssertAllFieldsSet(message3);
343 }
344
345 [Test]
346 public void ReadMaliciouslyLargeBlob()
347 {
348 MemoryStream ms = new MemoryStream();
349 CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
350
351 uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
352 output.WriteRawVarint32(tag);
353 output.WriteRawVarint32(0x7FFFFFFF);
354 output.WriteRawBytes(new byte[32]); // Pad with a few random bytes.
355 output.Flush();
356 ms.Position = 0;
357
358 CodedInputStream input = CodedInputStream.CreateInstance(ms);
csharptest123e5342011-06-03 14:15:21 -0500359 uint testtag;
360 string ignore;
361 Assert.IsTrue(input.ReadTag(out testtag, out ignore));
362 Assert.AreEqual(tag, testtag);
csharptest71f662c2011-05-20 15:15:34 -0500363
364 try
365 {
csharptestd2af9e92011-06-03 21:35:02 -0500366 ByteString bytes = null;
367 input.ReadBytes(ref bytes);
csharptest71f662c2011-05-20 15:15:34 -0500368 Assert.Fail("Should have thrown an exception!");
369 }
370 catch (InvalidProtocolBufferException)
371 {
372 // success.
373 }
374 }
375
376 private static TestRecursiveMessage MakeRecursiveMessage(int depth)
377 {
378 if (depth == 0)
379 {
380 return TestRecursiveMessage.CreateBuilder().SetI(5).Build();
381 }
382 else
383 {
384 return TestRecursiveMessage.CreateBuilder()
385 .SetA(MakeRecursiveMessage(depth - 1)).Build();
386 }
387 }
388
389 private static void AssertMessageDepth(TestRecursiveMessage message, int depth)
390 {
391 if (depth == 0)
392 {
393 Assert.IsFalse(message.HasA);
394 Assert.AreEqual(5, message.I);
395 }
396 else
397 {
398 Assert.IsTrue(message.HasA);
399 AssertMessageDepth(message.A, depth - 1);
400 }
401 }
402
403 [Test]
404 public void MaliciousRecursion()
405 {
406 ByteString data64 = MakeRecursiveMessage(64).ToByteString();
407 ByteString data65 = MakeRecursiveMessage(65).ToByteString();
408
409 AssertMessageDepth(TestRecursiveMessage.ParseFrom(data64), 64);
410
411 try
412 {
413 TestRecursiveMessage.ParseFrom(data65);
414 Assert.Fail("Should have thrown an exception!");
415 }
416 catch (InvalidProtocolBufferException)
417 {
418 // success.
419 }
420
421 CodedInputStream input = data64.CreateCodedInput();
422 input.SetRecursionLimit(8);
423 try
424 {
425 TestRecursiveMessage.ParseFrom(input);
426 Assert.Fail("Should have thrown an exception!");
427 }
428 catch (InvalidProtocolBufferException)
429 {
430 // success.
431 }
432 }
433
434 [Test]
435 public void SizeLimit()
436 {
437 // Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
438 // apply to the latter case.
439 MemoryStream ms = new MemoryStream(TestUtil.GetAllSet().ToByteString().ToByteArray());
440 CodedInputStream input = CodedInputStream.CreateInstance(ms);
441 input.SetSizeLimit(16);
442
443 try
444 {
445 TestAllTypes.ParseFrom(input);
446 Assert.Fail("Should have thrown an exception!");
447 }
448 catch (InvalidProtocolBufferException)
449 {
450 // success.
451 }
452 }
453
454 [Test]
455 public void ResetSizeCounter()
456 {
457 CodedInputStream input = CodedInputStream.CreateInstance(
458 new SmallBlockInputStream(new byte[256], 8));
459 input.SetSizeLimit(16);
460 input.ReadRawBytes(16);
461
462 try
463 {
464 input.ReadRawByte();
465 Assert.Fail("Should have thrown an exception!");
466 }
467 catch (InvalidProtocolBufferException)
468 {
469 // Success.
470 }
471
472 input.ResetSizeCounter();
473 input.ReadRawByte(); // No exception thrown.
474
475 try
476 {
477 input.ReadRawBytes(16); // Hits limit again.
478 Assert.Fail("Should have thrown an exception!");
479 }
480 catch (InvalidProtocolBufferException)
481 {
482 // Success.
483 }
484 }
485
486 /// <summary>
487 /// Tests that if we read an string that contains invalid UTF-8, no exception
488 /// is thrown. Instead, the invalid bytes are replaced with the Unicode
489 /// "replacement character" U+FFFD.
490 /// </summary>
491 [Test]
492 public void ReadInvalidUtf8()
493 {
494 MemoryStream ms = new MemoryStream();
495 CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
496
497 uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
498 output.WriteRawVarint32(tag);
499 output.WriteRawVarint32(1);
500 output.WriteRawBytes(new byte[] {0x80});
501 output.Flush();
502 ms.Position = 0;
503
504 CodedInputStream input = CodedInputStream.CreateInstance(ms);
csharptest123e5342011-06-03 14:15:21 -0500505
506 uint testtag;
507 string ignored;
508
509 Assert.IsTrue(input.ReadTag(out testtag, out ignored));
510 Assert.AreEqual(tag, testtag);
csharptestd2af9e92011-06-03 21:35:02 -0500511 string text = null;
512 input.ReadString(ref text);
csharptest71f662c2011-05-20 15:15:34 -0500513 Assert.AreEqual('\ufffd', text[0]);
514 }
515
516 /// <summary>
517 /// A stream which limits the number of bytes it reads at a time.
518 /// We use this to make sure that CodedInputStream doesn't screw up when
519 /// reading in small blocks.
520 /// </summary>
521 private sealed class SmallBlockInputStream : MemoryStream
522 {
523 private readonly int blockSize;
524
525 public SmallBlockInputStream(byte[] data, int blockSize)
526 : base(data)
527 {
528 this.blockSize = blockSize;
529 }
530
531 public override int Read(byte[] buffer, int offset, int count)
532 {
533 return base.Read(buffer, offset, Math.Min(count, blockSize));
534 }
535 }
csharptesta105eac2011-09-09 13:39:54 -0500536
537 enum TestNegEnum { None = 0, Value = -2 }
538
539 [Test]
540 public void TestNegativeEnum()
541 {
542 byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
543 CodedInputStream input = CodedInputStream.CreateInstance(bytes);
544 object unk;
545 TestNegEnum val = TestNegEnum.None;
546
547 Assert.IsTrue(input.ReadEnum(ref val, out unk));
548 Assert.IsTrue(input.IsAtEnd);
549 Assert.AreEqual(TestNegEnum.Value, val);
550 }
551
552 [Test]
553 public void TestNegativeEnumPackedArray()
554 {
555 int arraySize = 1 + (10 * 5);
556 int msgSize = 1 + 1 + arraySize;
557 byte[] bytes = new byte[msgSize];
558 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
559 output.WritePackedInt32Array(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
560
561 Assert.AreEqual(0, output.SpaceLeft);
562
563 CodedInputStream input = CodedInputStream.CreateInstance(bytes);
564 uint tag;
565 string name;
566 Assert.IsTrue(input.ReadTag(out tag, out name));
567
568 List<TestNegEnum> values = new List<TestNegEnum>();
569 ICollection<object> unk;
570 input.ReadEnumArray(tag, name, values, out unk);
571
572 Assert.AreEqual(2, values.Count);
573 Assert.AreEqual(TestNegEnum.None, values[0]);
574 Assert.AreEqual(TestNegEnum.Value, values[1]);
575
576 Assert.IsNotNull(unk);
577 Assert.AreEqual(4, unk.Count);
578 }
579
580 [Test]
581 public void TestNegativeEnumArray()
582 {
583 int arraySize = 1 + 1 + (11 * 5);
584 int msgSize = arraySize;
585 byte[] bytes = new byte[msgSize];
586 CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
587 output.WriteInt32Array(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
588
589 Assert.AreEqual(0, output.SpaceLeft);
590
591 CodedInputStream input = CodedInputStream.CreateInstance(bytes);
592 uint tag;
593 string name;
594 Assert.IsTrue(input.ReadTag(out tag, out name));
595
596 List<TestNegEnum> values = new List<TestNegEnum>();
597 ICollection<object> unk;
598 input.ReadEnumArray(tag, name, values, out unk);
599
600 Assert.AreEqual(2, values.Count);
601 Assert.AreEqual(TestNegEnum.None, values[0]);
602 Assert.AreEqual(TestNegEnum.Value, values[1]);
603
604 Assert.IsNotNull(unk);
605 Assert.AreEqual(4, unk.Count);
606 }
607
csharptest71f662c2011-05-20 15:15:34 -0500608 }
609}