Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Side by Side Diff: third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java

Issue 2590803003: Revert "third_party/protobuf: Update to HEAD (83d681ee2c)" (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 package com.google.protobuf.test;
32 import com.google.protobuf.*;
33
34 import protobuf_unittest.UnittestProto.TestAllTypes;
35 import protobuf_unittest.UnittestProto.TestRecursiveMessage;
36
37 import junit.framework.TestCase;
38
39 import java.io.ByteArrayInputStream;
40 import java.io.FilterInputStream;
41 import java.io.InputStream;
42 import java.io.IOException;
43
44 /**
45 * Unit test for {@link CodedInputStream}.
46 *
47 * @author kenton@google.com Kenton Varda
48 */
49 public class CodedInputStreamTest extends TestCase {
50 /**
51 * Helper to construct a byte array from a bunch of bytes. The inputs are
52 * actually ints so that I can use hex notation and not get stupid errors
53 * about precision.
54 */
55 private byte[] bytes(int... bytesAsInts) {
56 byte[] bytes = new byte[bytesAsInts.length];
57 for (int i = 0; i < bytesAsInts.length; i++) {
58 bytes[i] = (byte) bytesAsInts[i];
59 }
60 return bytes;
61 }
62
63 /**
64 * An InputStream which limits the number of bytes it reads at a time.
65 * We use this to make sure that CodedInputStream doesn't screw up when
66 * reading in small blocks.
67 */
68 private static final class SmallBlockInputStream extends FilterInputStream {
69 private final int blockSize;
70
71 public SmallBlockInputStream(byte[] data, int blockSize) {
72 this(new ByteArrayInputStream(data), blockSize);
73 }
74
75 public SmallBlockInputStream(InputStream in, int blockSize) {
76 super(in);
77 this.blockSize = blockSize;
78 }
79
80 public int read(byte[] b) throws IOException {
81 return super.read(b, 0, Math.min(b.length, blockSize));
82 }
83
84 public int read(byte[] b, int off, int len) throws IOException {
85 return super.read(b, off, Math.min(len, blockSize));
86 }
87 }
88
89 /**
90 * Parses the given bytes using readRawVarint32() and readRawVarint64() and
91 * checks that the result matches the given value.
92 */
93 private void assertReadVarint(byte[] data, long value) throws Exception {
94 CodedInputStream input = CodedInputStream.newInstance(data);
95 assertEquals((int)value, input.readRawVarint32());
96
97 input = CodedInputStream.newInstance(data);
98 assertEquals(value, input.readRawVarint64());
99 assertTrue(input.isAtEnd());
100
101 // Try different block sizes.
102 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
103 input = CodedInputStream.newInstance(
104 new SmallBlockInputStream(data, blockSize));
105 assertEquals((int)value, input.readRawVarint32());
106
107 input = CodedInputStream.newInstance(
108 new SmallBlockInputStream(data, blockSize));
109 assertEquals(value, input.readRawVarint64());
110 assertTrue(input.isAtEnd());
111 }
112
113 // Try reading direct from an InputStream. We want to verify that it
114 // doesn't read past the end of the input, so we copy to a new, bigger
115 // array first.
116 byte[] longerData = new byte[data.length + 1];
117 System.arraycopy(data, 0, longerData, 0, data.length);
118 InputStream rawInput = new ByteArrayInputStream(longerData);
119 }
120
121 /**
122 * Parses the given bytes using readRawVarint32() and readRawVarint64() and
123 * expects them to fail with an InvalidProtocolBufferException whose
124 * description matches the given one.
125 */
126 private void assertReadVarintFailure(
127 InvalidProtocolBufferException expected, byte[] data)
128 throws Exception {
129 CodedInputStream input = CodedInputStream.newInstance(data);
130 try {
131 input.readRawVarint32();
132 fail("Should have thrown an exception.");
133 } catch (InvalidProtocolBufferException e) {
134 assertEquals(expected.getMessage(), e.getMessage());
135 }
136
137 input = CodedInputStream.newInstance(data);
138 try {
139 input.readRawVarint64();
140 fail("Should have thrown an exception.");
141 } catch (InvalidProtocolBufferException e) {
142 assertEquals(expected.getMessage(), e.getMessage());
143 }
144 }
145
146 /** Tests readRawVarint32() and readRawVarint64(). */
147 public void testReadVarint() throws Exception {
148 assertReadVarint(bytes(0x00), 0);
149 assertReadVarint(bytes(0x01), 1);
150 assertReadVarint(bytes(0x7f), 127);
151 // 14882
152 assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
153 // 2961488830
154 assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
155 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
156 (0x0bL << 28));
157
158 // 64-bit
159 // 7256456126
160 assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
161 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
162 (0x1bL << 28));
163 // 41256202580718336
164 assertReadVarint(
165 bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
166 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
167 (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
168 // 11964378330978735131
169 assertReadVarint(
170 bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
171 (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
172 (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
173 (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
174 }
175
176 /**
177 * Parses the given bytes using readRawLittleEndian32() and checks
178 * that the result matches the given value.
179 */
180 private void assertReadLittleEndian32(byte[] data, int value)
181 throws Exception {
182 CodedInputStream input = CodedInputStream.newInstance(data);
183 assertEquals(value, input.readRawLittleEndian32());
184 assertTrue(input.isAtEnd());
185
186 // Try different block sizes.
187 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
188 input = CodedInputStream.newInstance(
189 new SmallBlockInputStream(data, blockSize));
190 assertEquals(value, input.readRawLittleEndian32());
191 assertTrue(input.isAtEnd());
192 }
193 }
194
195 /**
196 * Parses the given bytes using readRawLittleEndian64() and checks
197 * that the result matches the given value.
198 */
199 private void assertReadLittleEndian64(byte[] data, long value)
200 throws Exception {
201 CodedInputStream input = CodedInputStream.newInstance(data);
202 assertEquals(value, input.readRawLittleEndian64());
203 assertTrue(input.isAtEnd());
204
205 // Try different block sizes.
206 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
207 input = CodedInputStream.newInstance(
208 new SmallBlockInputStream(data, blockSize));
209 assertEquals(value, input.readRawLittleEndian64());
210 assertTrue(input.isAtEnd());
211 }
212 }
213
214 /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
215 public void testReadLittleEndian() throws Exception {
216 assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
217 assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
218
219 assertReadLittleEndian64(
220 bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
221 0x123456789abcdef0L);
222 assertReadLittleEndian64(
223 bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
224 0x9abcdef012345678L);
225 }
226
227 /** Test decodeZigZag32() and decodeZigZag64(). */
228 public void testDecodeZigZag() throws Exception {
229 assertEquals( 0, CodedInputStream.decodeZigZag32(0));
230 assertEquals(-1, CodedInputStream.decodeZigZag32(1));
231 assertEquals( 1, CodedInputStream.decodeZigZag32(2));
232 assertEquals(-2, CodedInputStream.decodeZigZag32(3));
233 assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
234 assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
235 assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
236 assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
237
238 assertEquals( 0, CodedInputStream.decodeZigZag64(0));
239 assertEquals(-1, CodedInputStream.decodeZigZag64(1));
240 assertEquals( 1, CodedInputStream.decodeZigZag64(2));
241 assertEquals(-2, CodedInputStream.decodeZigZag64(3));
242 assertEquals(0x000000003FFFFFFFL,
243 CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
244 assertEquals(0xFFFFFFFFC0000000L,
245 CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
246 assertEquals(0x000000007FFFFFFFL,
247 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
248 assertEquals(0xFFFFFFFF80000000L,
249 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
250 assertEquals(0x7FFFFFFFFFFFFFFFL,
251 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
252 assertEquals(0x8000000000000000L,
253 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
254 }
255
256 /** Tests reading and parsing a whole message with every field type. */
257 public void testReadWholeMessage() throws Exception {
258 TestAllTypes message = TestUtil.getAllSet();
259
260 byte[] rawBytes = message.toByteArray();
261 assertEquals(rawBytes.length, message.getSerializedSize());
262
263 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
264 TestUtil.assertAllFieldsSet(message2);
265
266 // Try different block sizes.
267 for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
268 message2 = TestAllTypes.parseFrom(
269 new SmallBlockInputStream(rawBytes, blockSize));
270 TestUtil.assertAllFieldsSet(message2);
271 }
272 }
273
274 /** Tests skipField(). */
275 public void testSkipWholeMessage() throws Exception {
276 TestAllTypes message = TestUtil.getAllSet();
277 byte[] rawBytes = message.toByteArray();
278
279 // Create two parallel inputs. Parse one as unknown fields while using
280 // skipField() to skip each field on the other. Expect the same tags.
281 CodedInputStream input1 = CodedInputStream.newInstance(rawBytes);
282 CodedInputStream input2 = CodedInputStream.newInstance(rawBytes);
283 UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
284
285 while (true) {
286 int tag = input1.readTag();
287 assertEquals(tag, input2.readTag());
288 if (tag == 0) {
289 break;
290 }
291 unknownFields.mergeFieldFrom(tag, input1);
292 input2.skipField(tag);
293 }
294 }
295
296 /**
297 * Test that a bug in skipRawBytes() has been fixed: if the skip skips
298 * exactly up to a limit, this should not break things.
299 */
300 public void testSkipRawBytesBug() throws Exception {
301 byte[] rawBytes = new byte[] { 1, 2 };
302 CodedInputStream input = CodedInputStream.newInstance(rawBytes);
303
304 int limit = input.pushLimit(1);
305 input.skipRawBytes(1);
306 input.popLimit(limit);
307 assertEquals(2, input.readRawByte());
308 }
309
310 /**
311 * Test that a bug in skipRawBytes() has been fixed: if the skip skips
312 * past the end of a buffer with a limit that has been set past the end of
313 * that buffer, this should not break things.
314 */
315 public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
316 byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
317 CodedInputStream input = CodedInputStream.newInstance(
318 new SmallBlockInputStream(rawBytes, 3));
319
320 int limit = input.pushLimit(4);
321 // In order to expose the bug we need to read at least one byte to prime the
322 // buffer inside the CodedInputStream.
323 assertEquals(1, input.readRawByte());
324 // Skip to the end of the limit.
325 input.skipRawBytes(3);
326 assertTrue(input.isAtEnd());
327 input.popLimit(limit);
328 assertEquals(5, input.readRawByte());
329 }
330
331 public void testReadHugeBlob() throws Exception {
332 // Allocate and initialize a 1MB blob.
333 byte[] blob = new byte[1 << 20];
334 for (int i = 0; i < blob.length; i++) {
335 blob[i] = (byte)i;
336 }
337
338 // Make a message containing it.
339 TestAllTypes.Builder builder = TestAllTypes.newBuilder();
340 TestUtil.setAllFields(builder);
341 builder.setOptionalBytes(ByteString.copyFrom(blob));
342 TestAllTypes message = builder.build();
343
344 // Serialize and parse it. Make sure to parse from an InputStream, not
345 // directly from a ByteString, so that CodedInputStream uses buffered
346 // reading.
347 TestAllTypes message2 =
348 TestAllTypes.parseFrom(message.toByteString().newInput());
349
350 assertEquals(message.getOptionalBytes(), message2.getOptionalBytes());
351
352 // Make sure all the other fields were parsed correctly.
353 TestAllTypes message3 = TestAllTypes.newBuilder(message2)
354 .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
355 .build();
356 TestUtil.assertAllFieldsSet(message3);
357 }
358
359 public int makeTag(int number, int tag) {
360 return (number << 3) + tag;
361 }
362
363 public void testReadMaliciouslyLargeBlob() throws Exception {
364 ByteString.Output rawOutput = ByteString.newOutput();
365 CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
366
367 int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
368 output.writeRawVarint32(tag);
369 output.writeRawVarint32(0x7FFFFFFF);
370 output.writeRawBytes(new byte[32]); // Pad with a few random bytes.
371 output.flush();
372
373 CodedInputStream input = rawOutput.toByteString().newCodedInput();
374 assertEquals(tag, input.readTag());
375
376 try {
377 input.readBytes();
378 fail("Should have thrown an exception!");
379 } catch (InvalidProtocolBufferException e) {
380 // success.
381 }
382 }
383
384 private TestRecursiveMessage makeRecursiveMessage(int depth) {
385 if (depth == 0) {
386 return TestRecursiveMessage.newBuilder().setI(5).build();
387 } else {
388 return TestRecursiveMessage.newBuilder()
389 .setA(makeRecursiveMessage(depth - 1)).build();
390 }
391 }
392
393 private void assertMessageDepth(TestRecursiveMessage message, int depth) {
394 if (depth == 0) {
395 assertFalse(message.hasA());
396 assertEquals(5, message.getI());
397 } else {
398 assertTrue(message.hasA());
399 assertMessageDepth(message.getA(), depth - 1);
400 }
401 }
402
403 public void testResetSizeCounter() throws Exception {
404 CodedInputStream input = CodedInputStream.newInstance(
405 new SmallBlockInputStream(new byte[256], 8));
406 input.setSizeLimit(16);
407 input.readRawBytes(16);
408 assertEquals(16, input.getTotalBytesRead());
409
410 try {
411 input.readRawByte();
412 fail("Should have thrown an exception!");
413 } catch (InvalidProtocolBufferException e) {
414 // success.
415 }
416
417 input.resetSizeCounter();
418 assertEquals(0, input.getTotalBytesRead());
419 input.readRawByte(); // No exception thrown.
420 input.resetSizeCounter();
421 assertEquals(0, input.getTotalBytesRead());
422 }
423
424 /**
425 * Tests that if we read an string that contains invalid UTF-8, no exception
426 * is thrown. Instead, the invalid bytes are replaced with the Unicode
427 * "replacement character" U+FFFD.
428 */
429 public void testReadInvalidUtf8() throws Exception {
430 ByteString.Output rawOutput = ByteString.newOutput();
431 CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
432
433 int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
434 output.writeRawVarint32(tag);
435 output.writeRawVarint32(1);
436 output.writeRawBytes(new byte[] { (byte)0x80 });
437 output.flush();
438
439 CodedInputStream input = rawOutput.toByteString().newCodedInput();
440 assertEquals(tag, input.readTag());
441 String text = input.readString();
442 assertEquals(0xfffd, text.charAt(0));
443 }
444
445 public void testReadFromSlice() throws Exception {
446 byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
447 CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
448 assertEquals(0, in.getTotalBytesRead());
449 for (int i = 3; i < 8; i++) {
450 assertEquals(i, in.readRawByte());
451 assertEquals(i-2, in.getTotalBytesRead());
452 }
453 // eof
454 assertEquals(0, in.readTag());
455 assertEquals(5, in.getTotalBytesRead());
456 }
457
458 public void testInvalidTag() throws Exception {
459 // Any tag number which corresponds to field number zero is invalid and
460 // should throw InvalidProtocolBufferException.
461 for (int i = 0; i < 8; i++) {
462 try {
463 CodedInputStream.newInstance(bytes(i)).readTag();
464 fail("Should have thrown an exception.");
465 } catch (InvalidProtocolBufferException e) {
466 }
467 }
468 }
469 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698