/* * 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.util; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import com.facebook.common.internal.Closeables; import org.robolectric.RobolectricTestRunner; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import static org.junit.Assert.*; import static org.mockito.Mockito.*; /** * Tests for {@link StreamUtil} */ @RunWith(RobolectricTestRunner.class) public class StreamUtilTest { /** * Verify that using a ByteArrayInputStream does not allocate a new byte array. */ @Test public void testByteArrayInputStream() throws Exception { byte[] bytes = new byte[8]; InputStream input = new ByteArrayInputStream(bytes); try { byte[] bytesRead = StreamUtil.getBytesFromStream(input); assertTrue(Arrays.equals(bytes, bytesRead)); } finally { Closeables.close(input, true); } } /** * Verify that using an offset with ByteArrayInputStream still produces correct output. */ @Test public void testByteArrayInputStreamWithOffset() throws Exception { byte[] bytes = new byte[] {0, 1, 2, 3, 4}; InputStream input = new ByteArrayInputStream(bytes, 1, 4); try { byte[] bytesRead = StreamUtil.getBytesFromStream(input); byte[] expectedBytes = new byte[] {1, 2, 3, 4}; assertTrue(Arrays.equals(expectedBytes, bytesRead)); } finally { Closeables.close(input, true); } } /** * Verify getting a byte array from a FileInputStream. */ @Test public void testFileInputStream() throws Exception { checkFileInputStream(4); checkFileInputStream(64 * 1024 + 5); // Don't end on an even byte boundary } @Test public void testSuccessfulSkip() throws Exception { InputStream inputStream = mock(InputStream.class); when(inputStream.skip(anyLong())).thenReturn(2L); assertEquals(10, StreamUtil.skip(inputStream, 10)); InOrder order = inOrder(inputStream); order.verify(inputStream).skip(10); order.verify(inputStream).skip(8); order.verify(inputStream).skip(6); order.verify(inputStream).skip(4); order.verify(inputStream).skip(2); verifyNoMoreInteractions(inputStream); } @Test public void testUnsuccessfulSkip() throws Exception { InputStream inputStream = mock(InputStream.class); when(inputStream.skip(anyLong())).thenReturn(3L, 5L, 0L, 6L, 0L); when(inputStream.read()).thenReturn(3, -1); assertEquals(15, StreamUtil.skip(inputStream, 20)); InOrder order = inOrder(inputStream); order.verify(inputStream).skip(20); order.verify(inputStream).skip(17); order.verify(inputStream).skip(12); order.verify(inputStream).read(); order.verify(inputStream).skip(11); order.verify(inputStream).skip(5); order.verify(inputStream).read(); verifyNoMoreInteractions(inputStream); } private void checkFileInputStream(int size) throws IOException { byte[] bytesToWrite = new byte[size]; for (int i=0; i<size; i++) { bytesToWrite[i] = (byte)i; // It's okay to truncate } File tmpFile = File.createTempFile("streamUtil", "test"); InputStream input = null; OutputStream output = null; try { output = new FileOutputStream(tmpFile); output.write(bytesToWrite); output.close(); input = new FileInputStream(tmpFile); byte[] bytesRead = StreamUtil.getBytesFromStream(input); assertTrue(Arrays.equals(bytesToWrite, bytesRead)); } finally { Closeables.close(input, true); Closeables.close(output, false); assertTrue(tmpFile.delete()); } } }