| Index: components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestTest.java
|
| diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestTest.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1f73fe206a91dd2c852a80a162e2b5d8d48b59b0
|
| --- /dev/null
|
| +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestTest.java
|
| @@ -0,0 +1,473 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.cronet_test_apk;
|
| +
|
| +import android.os.ConditionVariable;
|
| +
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.net.ExtendedResponseInfo;
|
| +import org.chromium.net.ResponseInfo;
|
| +import org.chromium.net.UrlRequest;
|
| +import org.chromium.net.UrlRequestException;
|
| +import org.chromium.net.UrlRequestListener;
|
| +
|
| +import java.net.URL;
|
| +import java.nio.ByteBuffer;
|
| +import java.util.concurrent.ExecutorService;
|
| +import java.util.concurrent.Executors;
|
| +
|
| +/**
|
| + * Test basic functionality of UrlRequest.
|
| + */
|
| +public class CronetUrlRequestTest extends CronetTestBase {
|
| + // URL used for base tests.
|
| + private static final String TEST_URL = "http://127.0.0.1:8000";
|
| + private static final String MOCK_SUCCESS_PATH = "success.txt";
|
| +
|
| + private static final String MOCK_CRONET_TEST_SUCCESS_URL =
|
| + "http://mock.http/success.txt";
|
| + private static final String MOCK_CRONET_TEST_REDIRECT_URL =
|
| + "http://mock.http/redirect.html";
|
| + private static final String MOCK_CRONET_TEST_NOTFOUND_URL =
|
| + "http://mock.http/notfound.html";
|
| + private static final String MOCK_CRONET_TEST_FAILED_URL =
|
| + "http://mock.failed.request/-2";
|
| +
|
| + // Executor for Cronet callbacks.
|
| + ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
| + CronetTestActivity mActivity;
|
| +
|
| + private enum LastCalled {
|
| + Nothing,
|
| + OnRedirect,
|
| + OnResponseStarted,
|
| + OnDataReceived,
|
| + OnComplete
|
| + };
|
| +
|
| + private enum FailureType {
|
| + None,
|
| + CancelSync,
|
| + CancelAsync,
|
| + ThrowSync
|
| + };
|
| +
|
| + class SimpleUrlRequestListener implements UrlRequestListener {
|
| +
|
| + protected ConditionVariable mComplete = new ConditionVariable();
|
| +
|
| + public ResponseInfo mResponseInfo;
|
| + public UrlRequestException mError;
|
| +
|
| + public int mHttpResponseDataLength = 0;
|
| +
|
| + public LastCalled mLastCalled = LastCalled.Nothing;
|
| +
|
| + public boolean mOnRedirectCalled = false;
|
| + public boolean mOnErrorCalled = false;
|
| +
|
| + public byte[] mLastDataReceivedAsBytes;
|
| + public String mResponseAsString = "";
|
| +
|
| + public SimpleUrlRequestListener() {
|
| + }
|
| +
|
| + @Override
|
| + public void onRedirect(UrlRequest request,
|
| + ResponseInfo info,
|
| + URL newLocation) {
|
| + assertEquals(LastCalled.Nothing, mLastCalled);
|
| + mLastCalled = LastCalled.OnRedirect;
|
| + mOnRedirectCalled = true;
|
| + }
|
| +
|
| + @Override
|
| + public void onResponseStarted(UrlRequest request, ResponseInfo info) {
|
| + assertTrue(mLastCalled == LastCalled.Nothing ||
|
| + mLastCalled == LastCalled.OnRedirect);
|
| + mLastCalled = LastCalled.OnResponseStarted;
|
| + mResponseInfo = info;
|
| + }
|
| +
|
| + @Override
|
| + public void onDataReceived(UrlRequest request,
|
| + ResponseInfo info,
|
| + ByteBuffer byteBuffer) {
|
| + assertTrue(mLastCalled == LastCalled.OnResponseStarted ||
|
| + mLastCalled == LastCalled.OnDataReceived);
|
| + mLastCalled = LastCalled.OnDataReceived;
|
| +
|
| + mHttpResponseDataLength += byteBuffer.capacity();
|
| + mLastDataReceivedAsBytes = new byte[byteBuffer.capacity()];
|
| + byteBuffer.get(mLastDataReceivedAsBytes);
|
| + mResponseAsString += new String(mLastDataReceivedAsBytes);
|
| + }
|
| +
|
| + @Override
|
| + public void onComplete(UrlRequest request, ExtendedResponseInfo info) {
|
| + assertTrue(mLastCalled == LastCalled.OnResponseStarted ||
|
| + mLastCalled == LastCalled.OnDataReceived);
|
| + mLastCalled = LastCalled.OnComplete;
|
| + mComplete.open();
|
| + }
|
| +
|
| + @Override
|
| + public void onError(UrlRequest request,
|
| + ResponseInfo info,
|
| + UrlRequestException error) {
|
| + mOnErrorCalled = true;
|
| + mError = error;
|
| + mComplete.open();
|
| + }
|
| +
|
| + public void blockForComplete() {
|
| + mComplete.block();
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + protected void setUp() throws Exception {
|
| + super.setUp();
|
| + mActivity = launchCronetTestApp();
|
| + // Make sure the activity was created as expected.
|
| + waitForActiveShellToBeDoneLoading();
|
| + assertTrue(UploadTestServer.startUploadTestServer());
|
| + // AddUrlInterceptors() after native application context is initialized.
|
| + MockUrlRequestJobUtil.addUrlInterceptors();
|
| + }
|
| +
|
| + public SimpleUrlRequestListener startAndWaitForComplete(String url)
|
| + throws Exception {
|
| + SimpleUrlRequestListener listener = new SimpleUrlRequestListener();
|
| + // Create request.
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + url, listener, mExecutor);
|
| + urlRequest.start();
|
| + listener.blockForComplete();
|
| + return listener;
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testSimpleGet() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + UploadTestServer.getEchoMethodURL());
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + // Default method is 'GET'.
|
| + assertEquals("GET", listener.mResponseAsString);
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnComplete);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testSetHttpMethod() throws Exception {
|
| + SimpleUrlRequestListener listener = new SimpleUrlRequestListener();
|
| + String methodName = "head";
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + UploadTestServer.getEchoMethodURL(), listener,
|
| + mExecutor);
|
| + // Try to set 'null' method.
|
| + try {
|
| + urlRequest.setHttpMethod(null);
|
| + fail("Exception not thrown");
|
| + } catch (NullPointerException e) {
|
| + assertEquals("Method is required.", e.getMessage());
|
| + }
|
| +
|
| + urlRequest.setHttpMethod(methodName);
|
| + urlRequest.start();
|
| + try {
|
| + urlRequest.setHttpMethod("toolate");
|
| + fail("Exception not thrown");
|
| + } catch (IllegalStateException e) {
|
| + assertEquals("Request is already started.", e.getMessage());
|
| + }
|
| + listener.blockForComplete();
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + assertEquals(methodName, listener.mResponseAsString);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testAddHeader() throws Exception {
|
| + SimpleUrlRequestListener listener = new SimpleUrlRequestListener();
|
| + String headerName = "header-name";
|
| + String headerValue = "header-value";
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + UploadTestServer.getEchoHeaderURL(headerName), listener,
|
| + mExecutor);
|
| + urlRequest.addHeader(headerName, headerValue);
|
| + urlRequest.start();
|
| + try {
|
| + urlRequest.addHeader("header2", "value");
|
| + fail("Exception not thrown");
|
| + } catch (IllegalStateException e) {
|
| + assertEquals("Request is already started.", e.getMessage());
|
| + }
|
| + listener.blockForComplete();
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + assertEquals(headerValue, listener.mResponseAsString);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testBadHeaderName() throws Exception {
|
| + SimpleUrlRequestListener listener = new SimpleUrlRequestListener();
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + TEST_URL, listener, mExecutor);
|
| + try {
|
| + urlRequest.addHeader("header:name", "headervalue");
|
| + fail("IllegalArgumentException not thrown.");
|
| + } catch (IllegalArgumentException e) {
|
| + assertEquals("Invalid header.", e.getMessage());
|
| + }
|
| +
|
| + try {
|
| + urlRequest.addHeader("headername", "bad header\r\nvalue");
|
| + fail("IllegalArgumentException not thrown.");
|
| + } catch (IllegalArgumentException e) {
|
| + assertEquals("Invalid header.", e.getMessage());
|
| + }
|
| +
|
| + try {
|
| + urlRequest.addHeader("headername", null);
|
| + fail("NullPointerException not thrown.");
|
| + } catch (NullPointerException e) {
|
| + assertEquals("Invalid header.", e.getMessage());
|
| + }
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockSuccess() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MOCK_CRONET_TEST_SUCCESS_URL);
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + assertTrue(listener.mHttpResponseDataLength != 0);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnComplete);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockRedirect() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MOCK_CRONET_TEST_REDIRECT_URL);
|
| + ResponseInfo mResponseInfo = listener.mResponseInfo;
|
| + assertTrue(listener.mOnRedirectCalled);
|
| + assertEquals(200, mResponseInfo.getHttpStatusCode());
|
| + assertEquals(MOCK_CRONET_TEST_SUCCESS_URL,
|
| + mResponseInfo.getUrl());
|
| + assertEquals(2, mResponseInfo.getUrlChain().length);
|
| + assertEquals(MOCK_CRONET_TEST_REDIRECT_URL,
|
| + mResponseInfo.getUrlChain()[0]);
|
| + assertEquals(MOCK_CRONET_TEST_SUCCESS_URL,
|
| + mResponseInfo.getUrlChain()[1]);
|
| + assertTrue(listener.mHttpResponseDataLength != 0);
|
| + assertTrue(listener.mOnRedirectCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnComplete);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockNotFound() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MOCK_CRONET_TEST_NOTFOUND_URL);
|
| + assertEquals(404, listener.mResponseInfo.getHttpStatusCode());
|
| + assertTrue(listener.mHttpResponseDataLength != 0);
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertFalse(listener.mOnErrorCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnComplete);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockFailed() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MOCK_CRONET_TEST_FAILED_URL);
|
| + assertEquals(null, listener.mResponseInfo);
|
| + assertEquals(0, listener.mHttpResponseDataLength);
|
| + assertNotNull(listener.mError);
|
| + assertEquals(-2, listener.mError.netError());
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertTrue(listener.mOnErrorCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.Nothing);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockStartAsyncError() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MockUrlRequestJobUtil.getMockUrlWithFailure(
|
| + MOCK_SUCCESS_PATH,
|
| + MockUrlRequestJobUtil.FailurePhase.START,
|
| + -3));
|
| + assertNull(listener.mResponseInfo);
|
| + assertNotNull(listener.mError);
|
| + assertEquals(-3, listener.mError.netError());
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertTrue(listener.mOnErrorCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.Nothing);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockReadDataSyncError() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MockUrlRequestJobUtil.getMockUrlWithFailure(
|
| + MOCK_SUCCESS_PATH,
|
| + MockUrlRequestJobUtil.FailurePhase.READ_SYNC,
|
| + -5));
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + assertNotNull(listener.mError);
|
| + assertEquals(-5, listener.mError.netError());
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertTrue(listener.mOnErrorCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnResponseStarted);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testMockReadDataAsyncError() throws Exception {
|
| + SimpleUrlRequestListener listener = startAndWaitForComplete(
|
| + MockUrlRequestJobUtil.getMockUrlWithFailure(
|
| + MOCK_SUCCESS_PATH,
|
| + MockUrlRequestJobUtil.FailurePhase.READ_ASYNC,
|
| + -5));
|
| + assertEquals(200, listener.mResponseInfo.getHttpStatusCode());
|
| + assertNotNull(listener.mError);
|
| + assertEquals(-5, listener.mError.netError());
|
| + assertFalse(listener.mOnRedirectCalled);
|
| + assertTrue(listener.mOnErrorCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnResponseStarted);
|
| + }
|
| +
|
| + class CancelingUrlRequestListener extends SimpleUrlRequestListener {
|
| +
|
| + FailureType mFailureType = FailureType.None;
|
| + LastCalled mFailureStep = LastCalled.Nothing;
|
| +
|
| + ExecutorService mExecutor;
|
| +
|
| + public CancelingUrlRequestListener(ExecutorService executor) {
|
| + mExecutor = executor;
|
| + }
|
| +
|
| + @Override
|
| + public void onRedirect(UrlRequest request,
|
| + ResponseInfo info,
|
| + URL newLocation) {
|
| + super.onRedirect(request, info, newLocation);
|
| + maybeThrowOrCancel(request);
|
| + }
|
| +
|
| + @Override
|
| + public void onResponseStarted(UrlRequest request, ResponseInfo info) {
|
| + super.onResponseStarted(request, info);
|
| + maybeThrowOrCancel(request);
|
| + }
|
| +
|
| + @Override
|
| + public void onDataReceived(UrlRequest request,
|
| + ResponseInfo info,
|
| + ByteBuffer byteBuffer) {
|
| + super.onDataReceived(request, info, byteBuffer);
|
| + maybeThrowOrCancel(request);
|
| + }
|
| +
|
| + @Override
|
| + public void onComplete(UrlRequest request, ExtendedResponseInfo info) {
|
| + super.onComplete(request, info);
|
| + maybeThrowOrCancel(request);
|
| + }
|
| +
|
| + private void maybeThrowOrCancel(final UrlRequest request) {
|
| + if (mLastCalled != mFailureStep) {
|
| + return;
|
| + }
|
| + if (mFailureType == FailureType.None) {
|
| + return;
|
| + }
|
| + if (mFailureType == FailureType.ThrowSync) {
|
| + throw new IllegalStateException("Listener Exception.");
|
| + }
|
| + Runnable task = new Runnable() {
|
| + public void run() {
|
| + request.cancel();
|
| + mComplete.open();
|
| + }
|
| + };
|
| + if (mFailureType == FailureType.CancelAsync) {
|
| + mExecutor.execute(task);
|
| + } else {
|
| + task.run();
|
| + }
|
| + }
|
| + }
|
| +
|
| + private void throwOrCancel(FailureType failureType, LastCalled failureStep,
|
| + boolean expectResponseInfo, boolean expectError) {
|
| + CancelingUrlRequestListener listener =
|
| + new CancelingUrlRequestListener(mExecutor);
|
| + listener.mFailureType = failureType;
|
| + listener.mFailureStep = failureStep;
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + MOCK_CRONET_TEST_REDIRECT_URL, listener, mExecutor);
|
| + urlRequest.start();
|
| + listener.blockForComplete();
|
| + assertTrue(listener.mOnRedirectCalled);
|
| + assertEquals(listener.mLastCalled, failureStep);
|
| + assertTrue(urlRequest.isCanceled());
|
| + assertEquals(expectResponseInfo, listener.mResponseInfo != null);
|
| + assertEquals(expectError, listener.mError != null);
|
| + assertEquals(expectError, listener.mOnErrorCalled);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testFailures() throws Exception {
|
| + throwOrCancel(FailureType.CancelSync, LastCalled.OnRedirect,
|
| + false, false);
|
| + throwOrCancel(FailureType.CancelAsync, LastCalled.OnRedirect,
|
| + false, false);
|
| + throwOrCancel(FailureType.ThrowSync, LastCalled.OnRedirect,
|
| + false, true);
|
| +
|
| + throwOrCancel(FailureType.CancelSync, LastCalled.OnResponseStarted,
|
| + true, false);
|
| + throwOrCancel(FailureType.CancelAsync, LastCalled.OnResponseStarted,
|
| + true, false);
|
| + throwOrCancel(FailureType.ThrowSync, LastCalled.OnResponseStarted,
|
| + true, true);
|
| +
|
| + throwOrCancel(FailureType.CancelSync, LastCalled.OnDataReceived,
|
| + true, false);
|
| + throwOrCancel(FailureType.CancelAsync, LastCalled.OnDataReceived,
|
| + true, false);
|
| + throwOrCancel(FailureType.ThrowSync, LastCalled.OnDataReceived,
|
| + true, true);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Cronet"})
|
| + public void testThrowOnComplete() {
|
| + CancelingUrlRequestListener listener =
|
| + new CancelingUrlRequestListener(mExecutor);
|
| + listener.mFailureType = FailureType.ThrowSync;
|
| + listener.mFailureStep = LastCalled.OnComplete;
|
| + UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest(
|
| + MOCK_CRONET_TEST_REDIRECT_URL, listener, mExecutor);
|
| + urlRequest.start();
|
| + listener.blockForComplete();
|
| + assertTrue(listener.mOnRedirectCalled);
|
| + assertEquals(listener.mLastCalled, LastCalled.OnComplete);
|
| + assertFalse(urlRequest.isCanceled());
|
| + assertNotNull(listener.mResponseInfo);
|
| + assertNull(listener.mError);
|
| + assertFalse(listener.mOnErrorCalled);
|
| + }
|
| +}
|
|
|