/* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.common.streams; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Arrays; import java.util.Random; import com.facebook.testing.robolectric.v2.WithTestDefaultsRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; @RunWith(WithTestDefaultsRunner.class) public class LimitedInputStreamTest { private static final int RANDOM_SEED = 1023; private static final int BYTES_LENGTH = 1024; private static final int LIMITED_LENGTH = BYTES_LENGTH / 2; private byte[] mData; private byte[] mReadBuffer; private byte[] mZeroTail; private ByteArrayInputStream mOriginalStream; private LimitedInputStream mLimitedStream; @Before public void setUp() { mData = new byte[BYTES_LENGTH]; mReadBuffer = new byte[BYTES_LENGTH]; final Random random = new Random(RANDOM_SEED); random.nextBytes(mData); mZeroTail = new byte[BYTES_LENGTH - LIMITED_LENGTH]; Arrays.fill(mZeroTail, (byte) 0); mOriginalStream = new ByteArrayInputStream(mData); mLimitedStream = new LimitedInputStream(mOriginalStream, LIMITED_LENGTH); } @Test public void testBasic() throws Exception { assertEquals(LIMITED_LENGTH, mLimitedStream.available()); assertTrue(mLimitedStream.markSupported()); } @Test public void testDoesReadSingleBytes() throws Exception { for (int i = 0; i < LIMITED_LENGTH; ++i) { assertEquals(((int) mData[i]) & 0xFF, mLimitedStream.read()); } } @Test public void testDoesNotReadTooMuch_singleBytes() throws Exception { for (int i = 0; i < BYTES_LENGTH; ++i) { final int lastByte = mLimitedStream.read(); assertEquals(i >= LIMITED_LENGTH, lastByte == -1); } assertEquals(BYTES_LENGTH - LIMITED_LENGTH, mOriginalStream.available()); } @Test public void testDoesReadMultipleBytes() throws Exception { assertEquals(LIMITED_LENGTH, mLimitedStream.read(mReadBuffer, 0, LIMITED_LENGTH)); assertArrayEquals( Arrays.copyOfRange(mData, 0, LIMITED_LENGTH), Arrays.copyOfRange(mReadBuffer, 0, LIMITED_LENGTH)); assertArrayEquals( mZeroTail, Arrays.copyOfRange(mReadBuffer, LIMITED_LENGTH, BYTES_LENGTH)); } @Test public void testDoesNotReadTooMuch_multipleBytes() throws Exception { assertEquals(LIMITED_LENGTH, mLimitedStream.read(mReadBuffer, 0, BYTES_LENGTH)); final byte[] readBufferCopy = Arrays.copyOf(mReadBuffer, mReadBuffer.length); assertEquals(-1, mLimitedStream.read(mReadBuffer, 0, BYTES_LENGTH)); assertArrayEquals(readBufferCopy, mReadBuffer); assertEquals(BYTES_LENGTH - LIMITED_LENGTH, mOriginalStream.available()); } @Test public void testSkip() throws Exception { assertEquals(LIMITED_LENGTH / 2, mLimitedStream.skip(LIMITED_LENGTH / 2)); assertEquals(LIMITED_LENGTH / 2, mLimitedStream.read(mReadBuffer)); assertArrayEquals( Arrays.copyOfRange(mData, LIMITED_LENGTH / 2, LIMITED_LENGTH), Arrays.copyOfRange(mReadBuffer, 0, LIMITED_LENGTH / 2)); } @Test public void testDoesNotReadTooMuch_skip() throws Exception { assertEquals(LIMITED_LENGTH, mLimitedStream.skip(BYTES_LENGTH)); assertEquals(0, mLimitedStream.skip(BYTES_LENGTH)); assertEquals(BYTES_LENGTH - LIMITED_LENGTH, mOriginalStream.available()); } @Test public void testDoesMark() throws Exception { mLimitedStream.mark(BYTES_LENGTH); mLimitedStream.read(mReadBuffer); final byte[] readBufferCopy = Arrays.copyOf(mReadBuffer, mReadBuffer.length); Arrays.fill(mReadBuffer, (byte) 0); mLimitedStream.reset(); assertEquals(LIMITED_LENGTH, mLimitedStream.read(mReadBuffer)); assertArrayEquals(readBufferCopy, mReadBuffer); } @Test public void testResetsMultipleTimes() throws Exception { mLimitedStream.mark(BYTES_LENGTH); mLimitedStream.read(mReadBuffer); final byte[] readBufferCopy = Arrays.copyOf(mReadBuffer, mReadBuffer.length); // first reset mLimitedStream.reset(); assertEquals(LIMITED_LENGTH, mLimitedStream.read(mReadBuffer)); // second reset Arrays.fill(mReadBuffer, (byte) 0); mLimitedStream.reset(); assertEquals(LIMITED_LENGTH, mLimitedStream.read(mReadBuffer)); assertArrayEquals(readBufferCopy, mReadBuffer); } @Test public void testDoesNotReadTooMuch_reset() throws Exception { mLimitedStream.mark(BYTES_LENGTH); mLimitedStream.read(mReadBuffer); mLimitedStream.reset(); mLimitedStream.read(mReadBuffer); assertEquals(BYTES_LENGTH - LIMITED_LENGTH, mOriginalStream.available()); } @Test(expected = IOException.class) public void testDoesNotRestIfNotMarked() throws Exception { mLimitedStream.read(mReadBuffer); mLimitedStream.reset(); } @Test public void testMultipleMarks() throws IOException { mLimitedStream.mark(BYTES_LENGTH); assertEquals(LIMITED_LENGTH / 2, mLimitedStream.read(mReadBuffer, 0, LIMITED_LENGTH / 2)); mLimitedStream.mark(BYTES_LENGTH); assertEquals( LIMITED_LENGTH / 2, mLimitedStream.read(mReadBuffer, LIMITED_LENGTH / 2, LIMITED_LENGTH / 2)); mLimitedStream.reset(); assertEquals(LIMITED_LENGTH / 2, mLimitedStream.read(mReadBuffer)); assertArrayEquals( Arrays.copyOfRange(mReadBuffer, 0, LIMITED_LENGTH / 2), Arrays.copyOfRange(mReadBuffer, LIMITED_LENGTH / 2, LIMITED_LENGTH)); } }