@ -30,8 +30,6 @@
package com.google.protobuf ;
import static org.junit.Assert.assertArrayEquals ;
import protobuf_unittest.UnittestProto.BoolMessage ;
import protobuf_unittest.UnittestProto.Int32Message ;
import protobuf_unittest.UnittestProto.Int64Message ;
@ -445,6 +443,82 @@ public class CodedInputStreamTest extends TestCase {
}
}
/ * *
* Test we can do messages that are up to CodedInputStream # DEFAULT_SIZE_LIMIT
* in size ( 2G or Integer # MAX_SIZE ) .
* @throws IOException
* /
public void testParseMessagesCloseTo2G ( ) throws IOException {
byte [ ] serializedMessage = getBigSerializedMessage ( ) ;
// How many of these big messages do we need to take us near our 2G limit?
int count = Integer . MAX_VALUE / serializedMessage . length ;
// Now make an inputstream that will fake a near 2G message of messages
// returning our big serialized message 'count' times.
InputStream is = new RepeatingInputStream ( serializedMessage , count ) ;
// Parse should succeed!
TestAllTypes . parseFrom ( is ) ;
}
/ * *
* Test there is an exception if a message exceeds
* CodedInputStream # DEFAULT_SIZE_LIMIT in size ( 2G or Integer # MAX_SIZE ) .
* @throws IOException
* /
public void testParseMessagesOver2G ( ) throws IOException {
byte [ ] serializedMessage = getBigSerializedMessage ( ) ;
// How many of these big messages do we need to take us near our 2G limit?
int count = Integer . MAX_VALUE / serializedMessage . length ;
// Now add one to take us over the limit
count + + ;
// Now make an inputstream that will fake a near 2G message of messages
// returning our big serialized message 'count' times.
InputStream is = new RepeatingInputStream ( serializedMessage , count ) ;
try {
TestAllTypes . parseFrom ( is ) ;
fail ( "Should have thrown an exception!" ) ;
} catch ( InvalidProtocolBufferException e ) {
assertTrue ( e . getMessage ( ) . contains ( "too large" ) ) ;
}
}
/ *
* @return A serialized big message .
* /
private static byte [ ] getBigSerializedMessage ( ) {
byte [ ] value = new byte [ 16 * 1024 * 1024 ] ;
ByteString bsValue = ByteString . wrap ( value ) ;
return TestAllTypes . newBuilder ( ) . setOptionalBytes ( bsValue ) . build ( ) . toByteArray ( ) ;
}
/ *
* An input stream that repeats a byte arrays ' content a number of times .
* Simulates really large input without consuming loads of memory . Used above
* to test the parsing behavior when the input size exceeds 2G or close to it .
* /
private static class RepeatingInputStream extends InputStream {
private final byte [ ] serializedMessage ;
private final int count ;
private int index = 0 ;
private int offset = 0 ;
RepeatingInputStream ( byte [ ] serializedMessage , int count ) {
this . serializedMessage = serializedMessage ;
this . count = count ;
}
@Override
public int read ( ) throws IOException {
if ( this . offset = = this . serializedMessage . length ) {
this . index + + ;
this . offset = 0 ;
}
if ( this . index = = this . count ) {
return - 1 ;
}
return this . serializedMessage [ offset + + ] ;
}
}
private TestRecursiveMessage makeRecursiveMessage ( int depth ) {
if ( depth = = 0 ) {
return TestRecursiveMessage . newBuilder ( ) . setI ( 5 ) . build ( ) ;