Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestTest.java

Issue 586143002: Initial implementation of Cronet Async API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More tests, more comments, more cancel. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698