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 |