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

Side by Side Diff: components/cronet/android/test/javatests/src/org/chromium/net/MockUrlRequestJobTest.java

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

Powered by Google App Engine
This is Rietveld 408576698