| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.net; | |
| 6 | |
| 7 import android.test.suitebuilder.annotation.LargeTest; | |
| 8 import android.test.suitebuilder.annotation.SmallTest; | |
| 9 | |
| 10 import org.chromium.base.test.util.Feature; | |
| 11 import org.chromium.net.test.FailurePhase; | |
| 12 | |
| 13 import java.io.IOException; | |
| 14 import java.nio.ByteBuffer; | |
| 15 import java.util.HashMap; | |
| 16 import java.util.List; | |
| 17 import java.util.concurrent.Executors; | |
| 18 | |
| 19 /** | |
| 20 * Tests making requests using {@link ChromiumUrlRequest}. | |
| 21 */ | |
| 22 @SuppressWarnings("deprecation") | |
| 23 public class ChromiumUrlRequestTest extends CronetTestBase { | |
| 24 private CronetTestFramework mTestFramework; | |
| 25 private TestHttpUrlRequestListener mListener; | |
| 26 private HttpUrlRequest mRequest; | |
| 27 | |
| 28 @Override | |
| 29 protected void setUp() throws Exception { | |
| 30 super.setUp(); | |
| 31 mTestFramework = startCronetTestFrameworkForLegacyApi(null); | |
| 32 assertTrue(NativeTestServer.startNativeTestServer(getContext())); | |
| 33 MockUrlRequestJobFactory.setUp(); | |
| 34 } | |
| 35 | |
| 36 @Override | |
| 37 protected void tearDown() throws Exception { | |
| 38 NativeTestServer.shutdownNativeTestServer(); | |
| 39 super.tearDown(); | |
| 40 } | |
| 41 | |
| 42 // Helper function to create a HttpUrlRequest with the specified url. | |
| 43 private void createRequestAndWaitForComplete( | |
| 44 String url, boolean disableRedirects) { | |
| 45 HashMap<String, String> headers = new HashMap<String, String>(); | |
| 46 mListener = new TestHttpUrlRequestListener(); | |
| 47 mRequest = mTestFramework.mRequestFactory.createRequest( | |
| 48 url, HttpUrlRequest.REQUEST_PRIORITY_MEDIUM, headers, mListener)
; | |
| 49 if (disableRedirects) { | |
| 50 mRequest.disableRedirects(); | |
| 51 } | |
| 52 mRequest.start(); | |
| 53 mListener.blockForComplete(); | |
| 54 } | |
| 55 | |
| 56 /** | |
| 57 * Helper method to check that we are not calling methods on the native | |
| 58 * adapter after it has been destroyed. | |
| 59 */ | |
| 60 private static void checkAfterAdapterDestroyed(HttpUrlRequest request) { | |
| 61 try { | |
| 62 request.getAllHeaders(); | |
| 63 fail(); | |
| 64 } catch (IllegalStateException e) { | |
| 65 assertEquals("Adapter has been destroyed", e.getMessage()); | |
| 66 } | |
| 67 try { | |
| 68 request.getHeader("foo"); | |
| 69 fail(); | |
| 70 } catch (IllegalStateException e) { | |
| 71 assertEquals("Adapter has been destroyed", e.getMessage()); | |
| 72 } | |
| 73 try { | |
| 74 request.getNegotiatedProtocol(); | |
| 75 fail(); | |
| 76 } catch (IllegalStateException e) { | |
| 77 assertEquals("Adapter has been destroyed", e.getMessage()); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 @SmallTest | |
| 82 @Feature({"Cronet"}) | |
| 83 public void testSuccessURLRequest() throws Exception { | |
| 84 createRequestAndWaitForComplete( | |
| 85 NativeTestServer.getSuccessURL(), false); | |
| 86 assertEquals(NativeTestServer.getSuccessURL(), mListener.mUrl); | |
| 87 assertEquals(200, mListener.mHttpStatusCode); | |
| 88 assertEquals("OK", mListener.mHttpStatusText); | |
| 89 assertEquals("this is a text file\n", | |
| 90 new String(mListener.mResponseAsBytes)); | |
| 91 // Test that ChromiumUrlRequest caches information which is available | |
| 92 // after the native request adapter has been destroyed. | |
| 93 assertEquals(200, mRequest.getHttpStatusCode()); | |
| 94 assertEquals("OK", mRequest.getHttpStatusText()); | |
| 95 assertNull(mRequest.getException()); | |
| 96 checkAfterAdapterDestroyed(mRequest); | |
| 97 } | |
| 98 | |
| 99 @SmallTest | |
| 100 @Feature({"Cronet"}) | |
| 101 public void testRedirectURLRequest() throws Exception { | |
| 102 createRequestAndWaitForComplete( | |
| 103 NativeTestServer.getRedirectURL(), false); | |
| 104 // ChromiumUrlRequest does not expose the url after redirect. | |
| 105 assertEquals(NativeTestServer.getRedirectURL(), mListener.mUrl); | |
| 106 assertEquals(200, mListener.mHttpStatusCode); | |
| 107 assertEquals("OK", mListener.mHttpStatusText); | |
| 108 // Expect that the request is redirected to success.txt. | |
| 109 assertEquals("this is a text file\n", | |
| 110 new String(mListener.mResponseAsBytes)); | |
| 111 // Test that ChromiumUrlRequest caches information which is available | |
| 112 // after the native request adapter has been destroyed. | |
| 113 assertEquals(200, mRequest.getHttpStatusCode()); | |
| 114 assertEquals("OK", mRequest.getHttpStatusText()); | |
| 115 assertNull(mRequest.getException()); | |
| 116 checkAfterAdapterDestroyed(mRequest); | |
| 117 } | |
| 118 | |
| 119 @SmallTest | |
| 120 @Feature({"Cronet"}) | |
| 121 public void testNotFoundURLRequest() throws Exception { | |
| 122 createRequestAndWaitForComplete( | |
| 123 NativeTestServer.getNotFoundURL(), false); | |
| 124 assertEquals(NativeTestServer.getNotFoundURL(), mListener.mUrl); | |
| 125 assertEquals(404, mListener.mHttpStatusCode); | |
| 126 assertEquals("Not Found", mListener.mHttpStatusText); | |
| 127 assertEquals( | |
| 128 "<!DOCTYPE html>\n<html>\n<head>\n<title>Not found</title>\n" | |
| 129 + "<p>Test page loaded.</p>\n</head>\n</html>\n", | |
| 130 new String(mListener.mResponseAsBytes)); | |
| 131 // Test that ChromiumUrlRequest caches information which is available | |
| 132 // after the native request adapter has been destroyed. | |
| 133 assertEquals(404, mRequest.getHttpStatusCode()); | |
| 134 assertEquals("Not Found", mRequest.getHttpStatusText()); | |
| 135 assertNull(mRequest.getException()); | |
| 136 checkAfterAdapterDestroyed(mRequest); | |
| 137 } | |
| 138 | |
| 139 @SmallTest | |
| 140 @Feature({"Cronet"}) | |
| 141 public void testFailedURLRequest() throws Exception { | |
| 142 // -2 is the net error code for FAILED. See net_error_list.h. | |
| 143 int errorFailed = -2; | |
| 144 String failedUrl = MockUrlRequestJobFactory.getMockUrlWithFailure( | |
| 145 FailurePhase.START, errorFailed); | |
| 146 createRequestAndWaitForComplete(failedUrl, false); | |
| 147 assertEquals(failedUrl, mListener.mUrl); | |
| 148 assertEquals("", mListener.mHttpStatusText); | |
| 149 assertEquals(0, mListener.mHttpStatusCode); | |
| 150 // Test that ChromiumUrlRequest caches information which is available | |
| 151 // after the native request adapter has been destroyed. | |
| 152 assertEquals(0, mRequest.getHttpStatusCode()); | |
| 153 assertEquals("", mRequest.getHttpStatusText()); | |
| 154 assertEquals("System error: net::ERR_FAILED(-2)", | |
| 155 mRequest.getException().getMessage()); | |
| 156 checkAfterAdapterDestroyed(mRequest); | |
| 157 } | |
| 158 | |
| 159 @SmallTest | |
| 160 @Feature({"Cronet"}) | |
| 161 // Test that redirect can be disabled for a request. | |
| 162 public void testDisableRedirects() throws Exception { | |
| 163 createRequestAndWaitForComplete( | |
| 164 NativeTestServer.getRedirectURL(), true); | |
| 165 // Currently Cronet does not expose the url after redirect. | |
| 166 assertEquals(NativeTestServer.getRedirectURL(), mListener.mUrl); | |
| 167 assertEquals(302, mListener.mHttpStatusCode); | |
| 168 // url_request_adapter.cc does not populate status text when redirects a
re disabled. | |
| 169 assertEquals("", mListener.mHttpStatusText); | |
| 170 // Expect that the request is not redirected to success.txt. | |
| 171 assertNotNull(mListener.mResponseHeaders); | |
| 172 List<String> entry = mListener.mResponseHeaders.get("redirect-header"); | |
| 173 assertEquals(1, entry.size()); | |
| 174 assertEquals("header-value", entry.get(0)); | |
| 175 List<String> location = mListener.mResponseHeaders.get("Location"); | |
| 176 assertEquals(1, location.size()); | |
| 177 assertEquals("/success.txt", location.get(0)); | |
| 178 assertEquals("Request failed because there were too many redirects or " | |
| 179 + "redirects have been disabled", | |
| 180 mListener.mException.getMessage()); | |
| 181 // Test that ChromiumUrlRequest caches information which is available | |
| 182 // after the native request adapter has been destroyed. | |
| 183 assertEquals(302, mRequest.getHttpStatusCode()); | |
| 184 // url_request_adapter.cc does not populate status text when redirects a
re disabled. | |
| 185 assertEquals("", mRequest.getHttpStatusText()); | |
| 186 assertEquals("Request failed because there were too many redirects " | |
| 187 + "or redirects have been disabled", | |
| 188 mRequest.getException().getMessage()); | |
| 189 checkAfterAdapterDestroyed(mRequest); | |
| 190 } | |
| 191 | |
| 192 /** | |
| 193 * TestByteChannel is used for making sure write is not called after the | |
| 194 * channel has been closed. Can synchronously cancel a request when write is | |
| 195 * called. | |
| 196 */ | |
| 197 static class TestByteChannel extends ChunkedWritableByteChannel { | |
| 198 HttpUrlRequest mRequestToCancelOnWrite; | |
| 199 | |
| 200 @Override | |
| 201 public int write(ByteBuffer byteBuffer) throws IOException { | |
| 202 assertTrue(isOpen()); | |
| 203 if (mRequestToCancelOnWrite != null) { | |
| 204 assertFalse(mRequestToCancelOnWrite.isCanceled()); | |
| 205 mRequestToCancelOnWrite.cancel(); | |
| 206 mRequestToCancelOnWrite = null; | |
| 207 } | |
| 208 return super.write(byteBuffer); | |
| 209 } | |
| 210 | |
| 211 @Override | |
| 212 public void close() { | |
| 213 assertTrue(isOpen()); | |
| 214 super.close(); | |
| 215 } | |
| 216 | |
| 217 /** | |
| 218 * Set request that will be synchronously canceled when write is called. | |
| 219 */ | |
| 220 public void setRequestToCancelOnWrite(HttpUrlRequest request) { | |
| 221 mRequestToCancelOnWrite = request; | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 @LargeTest | |
| 226 @Feature({"Cronet"}) | |
| 227 public void testNoWriteAfterCancelOnAnotherThread() throws Exception { | |
| 228 // This test verifies that WritableByteChannel.write is not called after | |
| 229 // WritableByteChannel.close if request is canceled from another | |
| 230 // thread. | |
| 231 for (int i = 0; i < 100; ++i) { | |
| 232 HashMap<String, String> headers = new HashMap<String, String>(); | |
| 233 TestByteChannel channel = new TestByteChannel(); | |
| 234 TestHttpUrlRequestListener listener = | |
| 235 new TestHttpUrlRequestListener(); | |
| 236 | |
| 237 // Create request. | |
| 238 final HttpUrlRequest request = | |
| 239 mTestFramework.mRequestFactory.createRequest(NativeTestServe
r.getSuccessURL(), | |
| 240 HttpUrlRequest.REQUEST_PRIORITY_LOW, headers, channe
l, listener); | |
| 241 request.start(); | |
| 242 listener.blockForStart(); | |
| 243 Runnable cancelTask = new Runnable() { | |
| 244 public void run() { | |
| 245 request.cancel(); | |
| 246 } | |
| 247 }; | |
| 248 Executors.newCachedThreadPool().execute(cancelTask); | |
| 249 listener.blockForComplete(); | |
| 250 assertFalse(channel.isOpen()); | |
| 251 // Since getAllHeaders and other methods in | |
| 252 // checkAfterAdapterDestroyed() acquire mLock, so this will happen | |
| 253 // after the adapter is destroyed. | |
| 254 checkAfterAdapterDestroyed(request); | |
| 255 } | |
| 256 } | |
| 257 | |
| 258 @SmallTest | |
| 259 @Feature({"Cronet"}) | |
| 260 public void testNoWriteAfterSyncCancel() throws Exception { | |
| 261 HashMap<String, String> headers = new HashMap<String, String>(); | |
| 262 TestByteChannel channel = new TestByteChannel(); | |
| 263 TestHttpUrlRequestListener listener = new TestHttpUrlRequestListener(); | |
| 264 | |
| 265 String data = "MyBigFunkyData"; | |
| 266 int repeatCount = 10000; | |
| 267 String mockUrl = MockUrlRequestJobFactory.getMockUrlForData(data, | |
| 268 repeatCount); | |
| 269 | |
| 270 // Create request. | |
| 271 final HttpUrlRequest request = mTestFramework.mRequestFactory.createRequ
est( | |
| 272 mockUrl, HttpUrlRequest.REQUEST_PRIORITY_LOW, headers, channel,
listener); | |
| 273 // Channel will cancel the request from the network thread during the | |
| 274 // first write. | |
| 275 channel.setRequestToCancelOnWrite(request); | |
| 276 request.start(); | |
| 277 listener.blockForComplete(); | |
| 278 assertTrue(request.isCanceled()); | |
| 279 assertFalse(channel.isOpen()); | |
| 280 // Test that ChromiumUrlRequest caches information which is available | |
| 281 // after the native request adapter has been destroyed. | |
| 282 // Since the request is canceled after onResponseStarted, status code | |
| 283 // should be 200. | |
| 284 assertEquals(200, request.getHttpStatusCode()); | |
| 285 assertEquals("OK", request.getHttpStatusText()); | |
| 286 checkAfterAdapterDestroyed(request); | |
| 287 } | |
| 288 | |
| 289 @SmallTest | |
| 290 @Feature({"Cronet"}) | |
| 291 public void testBigDataSyncReadRequest() throws Exception { | |
| 292 String data = "MyBigFunkyData"; | |
| 293 int dataLength = data.length(); | |
| 294 int repeatCount = 100000; | |
| 295 String mockUrl = MockUrlRequestJobFactory.getMockUrlForData(data, | |
| 296 repeatCount); | |
| 297 createRequestAndWaitForComplete(mockUrl, false); | |
| 298 assertEquals(mockUrl, mListener.mUrl); | |
| 299 for (int i = 0; i < repeatCount; ++i) { | |
| 300 assertEquals(data, mListener.mResponseAsString.substring( | |
| 301 dataLength * i, dataLength * (i + 1))); | |
| 302 } | |
| 303 } | |
| 304 } | |
| OLD | NEW |