/* * 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 com.facebook.stetho.common.Util; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.never; import static org.mockito.Matchers.any; import com.facebook.stetho.inspector.network.AsyncPrettyPrinter; import com.facebook.stetho.inspector.network.AsyncPrettyPrinterExecutorHolder; import dalvik.annotation.TestTargetClass; import org.junit.Before; import org.junit.Test; import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.Override; import java.lang.String; import java.util.ArrayList; import java.util.Arrays; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; public class AsyncPrettyPrintResponseBodyTest { private static final String TEST_REQUEST_ID = "1234"; private static final String TEST_HEADER_NAME = "header name"; private static final String TEST_HEADER_VALUE = "header value"; private static final String PRETTY_PRINT_PREFIX = "pretty printed result: "; private static final String[] UNREGISTERED_HEADER_NAMES = {"unregistered header name 1", "unregistered header name 2", "unregistered header name 3"}; private static final String[] UNREGISTERED_HEADER_VALUES = {"unregistered header value 1", "unregistered header value 2", "unregistered header value 3"}; private static final byte[] TEST_RESPONSE_BODY; private static final ByteArrayInputStream mInputStream; 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); } mInputStream = new ByteArrayInputStream(TEST_RESPONSE_BODY); } private AsyncPrettyPrinterRegistry mAsyncPrettyPrinterRegistry; private PrettyPrinterTestFactory mPrettyPrinterTestFactory; private ResponseBodyFileManager mResponseBodyFileManager; @Before public void setup() { mPrettyPrinterTestFactory = new PrettyPrinterTestFactory(); mResponseBodyFileManager = mock(ResponseBodyFileManager.class); mAsyncPrettyPrinterRegistry = new AsyncPrettyPrinterRegistry(); mAsyncPrettyPrinterRegistry.register(TEST_HEADER_NAME, mPrettyPrinterTestFactory); AsyncPrettyPrinterExecutorHolder.ensureInitialized(); } @Test public void testAsyncPrettyPrinterResult() throws IOException { StringWriter out = new StringWriter(); PrintWriter writer = new PrintWriter(out); AsyncPrettyPrinter mAsyncPrettyPrinter = mPrettyPrinterTestFactory.getInstance( TEST_HEADER_NAME, TEST_HEADER_VALUE); mAsyncPrettyPrinter.printTo(writer, mInputStream); assertEquals(PRETTY_PRINT_PREFIX + Arrays.toString(TEST_RESPONSE_BODY), out.toString()); } @Test public void testInitAsyncPrettyPrinterForResponseWithRegisteredHeader() { ArrayList<String> headerNames = new ArrayList<String>(); ArrayList<String> headerValues = new ArrayList<String>(); headerNames.add(UNREGISTERED_HEADER_NAMES[0]); headerNames.add(UNREGISTERED_HEADER_NAMES[1]); headerNames.add(TEST_HEADER_NAME); headerValues.add(UNREGISTERED_HEADER_VALUES[0]); headerValues.add(UNREGISTERED_HEADER_VALUES[1]); headerValues.add(TEST_HEADER_VALUE); TestInspectorResponse testResponse = new TestInspectorResponse( headerNames, headerValues, TEST_REQUEST_ID ); AsyncPrettyPrinter prettyPrinter = NetworkEventReporterImpl.createPrettyPrinterForResponse( testResponse, mAsyncPrettyPrinterRegistry); assertNotNull(prettyPrinter); } @Test public void testInitAsyncPrettyPrinterForResponseWithUnregisteredHeader() { ArrayList<String> headerNames = new ArrayList<String>(); ArrayList<String> headerValues = new ArrayList<String>(); headerNames.add(UNREGISTERED_HEADER_NAMES[0]); headerNames.add(UNREGISTERED_HEADER_NAMES[1]); headerNames.add(UNREGISTERED_HEADER_NAMES[2]); headerValues.add(UNREGISTERED_HEADER_VALUES[0]); headerValues.add(UNREGISTERED_HEADER_VALUES[1]); headerValues.add(UNREGISTERED_HEADER_VALUES[2]); TestInspectorResponse testResponse = new TestInspectorResponse( headerNames, headerValues, TEST_REQUEST_ID ); AsyncPrettyPrinter prettyPrinter = NetworkEventReporterImpl.createPrettyPrinterForResponse( testResponse, mAsyncPrettyPrinterRegistry); assertEquals(null, prettyPrinter); } @Test public void testGetInstanceWithUnmatchedHeader() { ArrayList<String> headerNames = new ArrayList<String>(); ArrayList<String> headerValues = new ArrayList<String>(); headerNames.add(UNREGISTERED_HEADER_NAMES[0]); headerNames.add(UNREGISTERED_HEADER_NAMES[1]); headerNames.add(TEST_HEADER_NAME); headerValues.add(UNREGISTERED_HEADER_VALUES[0]); headerValues.add(UNREGISTERED_HEADER_VALUES[1]); headerValues.add(UNREGISTERED_HEADER_VALUES[2]); TestInspectorResponse testResponse = new TestInspectorResponse( headerNames, headerValues, TEST_REQUEST_ID ); AsyncPrettyPrinter prettyPrinter = NetworkEventReporterImpl.createPrettyPrinterForResponse( testResponse, mAsyncPrettyPrinterRegistry); assertEquals(null, prettyPrinter); } private class PrettyPrinterTestFactory extends DownloadingAsyncPrettyPrinterFactory { @Override protected void doPrint(PrintWriter output, InputStream payload, String schema) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); Util.copy(payload, out, new byte[1024]); String prettifiedContent = PRETTY_PRINT_PREFIX + Arrays.toString(out.toByteArray()); output.write(prettifiedContent); output.close(); } @Override @Nullable protected MatchResult matchAndParseHeader(String headerName, String headerValue) { if (headerName.equals(TEST_HEADER_NAME) && headerValue.equals(TEST_HEADER_VALUE)) { return new MatchResult("https://www.facebook.com", PrettyPrinterDisplayType.TEXT); } else { return null; } } } private class TestInspectorResponse implements NetworkEventReporter.InspectorResponse { private ArrayList<String> mHeaderNames; private ArrayList<String> mHeaderValues; private String mRequestId; public TestInspectorResponse( ArrayList<String> headerNames, ArrayList<String> headerValues, String requestId) { mHeaderNames = headerNames; mHeaderValues = headerValues; mRequestId = requestId; } public int headerCount() { return mHeaderNames.size(); } public String headerName(int index) { return mHeaderNames.get(index); } public String headerValue(int index) { return mHeaderValues.get(index); } @Nullable public String firstHeaderValue(String name) { return mHeaderValues.get(0); } public String requestId() { return mRequestId; } public String url() { return "test url"; } public int statusCode() { return 200; } public String reasonPhrase() { return "test reason phrase"; } public boolean connectionReused() { return false; } public int connectionId() { return 111; } public boolean fromDiskCache() { return false; } } /** * Returns the truncated byte value of position. */ private static byte positionToByte(int position) { return (byte) (position % 0xff); } }