/* * Copyright (c) 2014-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.stetho.inspector.network; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import com.facebook.stetho.inspector.console.CLog; import com.facebook.stetho.inspector.helper.ChromePeerManager; import com.facebook.stetho.inspector.protocol.module.Console; import static org.mockito.Mockito.mock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @RunWith(PowerMockRunner.class) @PrepareForTest(CLog.class) public class ResponseHandlingInputStreamTest { private static final String TEST_REQUEST_ID = "1234"; private static final byte[] TEST_RESPONSE_BODY; static { int responseBodyLength = 4096 * 2 + 2048; // span multiple buffers when tee-ing TEST_RESPONSE_BODY = new byte[responseBodyLength]; for (int i = 0; i < responseBodyLength; i++) { TEST_RESPONSE_BODY[i] = positionToByte(i); } } private ByteArrayOutputStream mTestOutputStream; private ResponseHandlingInputStream mResponseHandlingInputStream; private NetworkPeerManager mNetworkPeerManager; private NetworkEventReporterImpl mNetworkEventReporter; @Before public void setup() { mTestOutputStream = new ByteArrayOutputStream(); // The only place this is used is when trying to write to the console. Since we are going to // mock ResponseHandlingInputStream#writeToConsole passing null is fine. mNetworkPeerManager = null; mNetworkEventReporter = mock(NetworkEventReporterImpl.class); mResponseHandlingInputStream = new ResponseHandlingInputStream( new ByteArrayInputStream(TEST_RESPONSE_BODY), TEST_REQUEST_ID, mTestOutputStream, null /* decompressedCounter */, mNetworkPeerManager, new DefaultResponseHandler(mNetworkEventReporter, TEST_REQUEST_ID)); } @Test public void testReadOneByte() throws IOException { int result = mResponseHandlingInputStream.read(); assertEquals(TEST_RESPONSE_BODY[0], positionToByte(result)); assertBufferMatchesResponseBody(mTestOutputStream.toByteArray(), 1); PowerMockito.mockStatic(CLog.class); PowerMockito.doNothing().when(CLog.class); CLog.writeToConsole( Mockito.any(ChromePeerManager.class), Mockito.any(Console.MessageLevel.class), Mockito.any(Console.MessageSource.class), Mockito.anyString()); mResponseHandlingInputStream.close(); PowerMockito.verifyStatic(); } @Test public void testReadPartial() throws IOException { int numBytesToRead = TEST_RESPONSE_BODY.length / 2; byte[] tempReadingBuffer = new byte[numBytesToRead]; int result = mResponseHandlingInputStream.read(tempReadingBuffer, 0, numBytesToRead); assertEquals(numBytesToRead, result); assertBufferMatchesResponseBody(tempReadingBuffer, numBytesToRead); assertBufferMatchesResponseBody(mTestOutputStream.toByteArray(), numBytesToRead); PowerMockito.mockStatic(CLog.class); PowerMockito.doNothing().when(CLog.class); CLog.writeToConsole( Mockito.any(ChromePeerManager.class), Mockito.any(Console.MessageLevel.class), Mockito.any(Console.MessageSource.class), Mockito.anyString()); mResponseHandlingInputStream.close(); PowerMockito.verifyStatic(); } @Test public void testReadFully() throws IOException { byte[] tempReadingBuffer = new byte[TEST_RESPONSE_BODY.length]; int result = mResponseHandlingInputStream.read(tempReadingBuffer); assertEquals(TEST_RESPONSE_BODY.length, result); assertBufferMatchesResponseBody(tempReadingBuffer, TEST_RESPONSE_BODY.length); assertBufferMatchesResponseBody(mTestOutputStream.toByteArray(), TEST_RESPONSE_BODY.length); PowerMockito.mockStatic(CLog.class); PowerMockito.verifyZeroInteractions(CLog.class); mResponseHandlingInputStream.close(); PowerMockito.verifyStatic(); } @Test public void testSkipFew() throws IOException { long numBytesToSkip = TEST_RESPONSE_BODY.length / 2; long result = mResponseHandlingInputStream.skip(numBytesToSkip); assertEquals(numBytesToSkip, result); assertBufferMatchesResponseBody(mTestOutputStream.toByteArray(), (int) numBytesToSkip); PowerMockito.mockStatic(CLog.class); PowerMockito.doNothing().when(CLog.class); CLog.writeToConsole( Mockito.any(ChromePeerManager.class), Mockito.any(Console.MessageLevel.class), Mockito.any(Console.MessageSource.class), Mockito.anyString()); mResponseHandlingInputStream.close(); PowerMockito.verifyStatic(); } @Test public void testSkipMany() throws IOException { long numBytesToSkip = TEST_RESPONSE_BODY.length * 2; long result = mResponseHandlingInputStream.skip(numBytesToSkip); assertEquals((long) TEST_RESPONSE_BODY.length, result); assertBufferMatchesResponseBody(mTestOutputStream.toByteArray(), TEST_RESPONSE_BODY.length); PowerMockito.verifyZeroInteractions(CLog.class); mResponseHandlingInputStream.close(); } private static final class TestIOException extends IOException {} @Test public void testSwallowException() throws IOException { OutputStream exceptionOutputStream = new OutputStream() { @Override public void write(int oneByte) throws IOException { throw new TestIOException(); } }; ResponseHandlingInputStream responseHandlingInputStream = new ResponseHandlingInputStream( new ByteArrayInputStream(TEST_RESPONSE_BODY), TEST_REQUEST_ID, exceptionOutputStream, null /* decompressedCounter */, mNetworkPeerManager, new DefaultResponseHandler(mNetworkEventReporter, TEST_REQUEST_ID)); PowerMockito.mockStatic(CLog.class); responseHandlingInputStream.read(); PowerMockito.verifyStatic(); } /** * Returns the truncated byte value of position. */ private static byte positionToByte(int position) { return (byte) (position % 0xff); } /** * Asserts that buffer's length equal to count and matches the first count bytes of the * test response body. */ private static void assertBufferMatchesResponseBody(byte[] buffer, int count) { assertArrayEquals(Arrays.copyOf(TEST_RESPONSE_BODY, count), buffer); } }