OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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.urlconnection; | |
6 | |
7 import android.test.suitebuilder.annotation.SmallTest; | |
8 | |
9 import org.chromium.base.test.util.Feature; | |
10 | |
11 import org.chromium.net.CronetTestActivity; | |
12 import org.chromium.net.CronetTestBase; | |
13 import org.chromium.net.NativeTestServer; | |
14 | |
15 import java.io.ByteArrayOutputStream; | |
16 import java.io.InputStream; | |
17 import java.io.OutputStream; | |
18 import java.net.HttpURLConnection; | |
19 import java.net.URL; | |
20 | |
21 /** | |
22 * Tests the CronetBufferedOutputStream implementation. | |
23 */ | |
24 public class CronetBufferedOutputStreamTest extends CronetTestBase { | |
25 private static final String UPLOAD_DATA_STRING = "Nifty upload data!"; | |
26 private static final byte[] UPLOAD_DATA = UPLOAD_DATA_STRING.getBytes(); | |
27 private static final int REPEAT_COUNT = 100000; | |
28 private CronetTestActivity mActivity; | |
29 | |
30 @Override | |
31 protected void setUp() throws Exception { | |
32 super.setUp(); | |
33 mActivity = launchCronetTestApp(); | |
34 assertTrue(NativeTestServer.startNativeTestServer( | |
35 getInstrumentation().getTargetContext())); | |
36 } | |
37 | |
38 @Override | |
39 protected void tearDown() throws Exception { | |
40 NativeTestServer.shutdownNativeTestServer(); | |
41 super.tearDown(); | |
42 } | |
43 | |
44 @SmallTest | |
45 @Feature({"Cronet"}) | |
46 @CompareDefaultWithCronet | |
47 public void testPostAfterConnectionMade() throws Exception { | |
mmenke
2015/03/31 18:19:32
nit: Maybe testGetOutputStreamAfter...?
xunjieli
2015/04/01 17:04:09
Done.
| |
48 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
49 HttpURLConnection connection = | |
50 (HttpURLConnection) url.openConnection(); | |
51 connection.setDoOutput(true); | |
52 connection.setRequestMethod("POST"); | |
53 assertEquals(200, connection.getResponseCode()); | |
54 try { | |
55 connection.getOutputStream(); | |
56 fail(); | |
57 } catch (java.net.ProtocolException e) { | |
58 // Expected. | |
59 } | |
60 } | |
mmenke
2015/03/31 18:19:32
Should we have a similar test where we get the out
xunjieli
2015/04/01 17:04:09
Done.
| |
61 | |
62 @SmallTest | |
63 @Feature({"Cronet"}) | |
64 @CompareDefaultWithCronet | |
65 public void testPostWithContentLength() throws Exception { | |
66 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
67 HttpURLConnection connection = | |
68 (HttpURLConnection) url.openConnection(); | |
69 connection.setDoOutput(true); | |
70 connection.setRequestMethod("POST"); | |
71 byte[] largeData = getLargeData(); | |
72 connection.setRequestProperty("Content-Length", | |
73 Integer.toString(largeData.length)); | |
74 OutputStream out = connection.getOutputStream(); | |
75 int totalBytesWritten = 0; | |
76 // Number of bytes to write each time. It is incremented by one from 0. | |
77 int bytesToWrite = 0; | |
78 while (totalBytesWritten < largeData.length) { | |
79 if (bytesToWrite > largeData.length - totalBytesWritten) { | |
80 // Do not write out of bound. | |
81 bytesToWrite = largeData.length - totalBytesWritten; | |
82 } | |
83 out.write(largeData, totalBytesWritten, bytesToWrite); | |
84 totalBytesWritten += bytesToWrite; | |
85 bytesToWrite++; | |
86 } | |
87 assertEquals(200, connection.getResponseCode()); | |
88 assertEquals("OK", connection.getResponseMessage()); | |
89 checkLargeData(getResponseAsString(connection)); | |
90 connection.disconnect(); | |
91 } | |
92 | |
93 @SmallTest | |
94 @Feature({"Cronet"}) | |
95 @CompareDefaultWithCronet | |
96 public void testPostWithContentLengthOneMassiveWrite() throws Exception { | |
97 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
98 HttpURLConnection connection = | |
99 (HttpURLConnection) url.openConnection(); | |
100 connection.setDoOutput(true); | |
101 connection.setRequestMethod("POST"); | |
102 byte[] largeData = getLargeData(); | |
103 connection.setRequestProperty("Content-Length", | |
104 Integer.toString(largeData.length)); | |
105 OutputStream out = connection.getOutputStream(); | |
106 out.write(largeData); | |
107 assertEquals(200, connection.getResponseCode()); | |
108 assertEquals("OK", connection.getResponseMessage()); | |
109 checkLargeData(getResponseAsString(connection)); | |
110 connection.disconnect(); | |
111 } | |
112 | |
113 @SmallTest | |
114 @Feature({"Cronet"}) | |
115 @CompareDefaultWithCronet | |
116 public void testPostWithContentLengthWriteOneByte() throws Exception { | |
117 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
118 HttpURLConnection connection = | |
119 (HttpURLConnection) url.openConnection(); | |
120 connection.setDoOutput(true); | |
121 connection.setRequestMethod("POST"); | |
122 byte[] largeData = getLargeData(); | |
123 connection.setRequestProperty("Content-Length", | |
124 Integer.toString(largeData.length)); | |
125 OutputStream out = connection.getOutputStream(); | |
126 for (int i = 0; i < largeData.length; i++) { | |
127 out.write(largeData[i]); | |
128 } | |
129 assertEquals(200, connection.getResponseCode()); | |
130 assertEquals("OK", connection.getResponseMessage()); | |
131 checkLargeData(getResponseAsString(connection)); | |
132 connection.disconnect(); | |
133 } | |
134 | |
135 @SmallTest | |
136 @Feature({"Cronet"}) | |
137 @CompareDefaultWithCronet | |
138 public void testPostWithZeroContentLength() throws Exception { | |
139 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
140 HttpURLConnection connection = | |
141 (HttpURLConnection) url.openConnection(); | |
142 connection.setDoOutput(true); | |
143 connection.setRequestMethod("POST"); | |
144 connection.setRequestProperty("Content-Length", "0"); | |
145 assertEquals(200, connection.getResponseCode()); | |
146 assertEquals("OK", connection.getResponseMessage()); | |
147 assertEquals("", getResponseAsString(connection)); | |
148 connection.disconnect(); | |
149 } | |
150 | |
151 @SmallTest | |
152 @Feature({"Cronet"}) | |
153 @CompareDefaultWithCronet | |
154 public void testPostZeroByteWithoutContentLength() throws Exception { | |
155 // Make sure both implementation sets the Content-Length header to 0. | |
156 URL url = new URL(NativeTestServer.getEchoHeaderURL("Content-Length")); | |
157 HttpURLConnection connection = | |
158 (HttpURLConnection) url.openConnection(); | |
159 connection.setDoOutput(true); | |
160 connection.setRequestMethod("POST"); | |
161 assertEquals(200, connection.getResponseCode()); | |
162 assertEquals("OK", connection.getResponseMessage()); | |
163 assertEquals("0", getResponseAsString(connection)); | |
164 connection.disconnect(); | |
165 | |
166 // Make sure the server echos back empty body for both implementation. | |
mmenke
2015/03/31 18:19:32
nit: echoes (I'm not sure if echos is a valid alt
xunjieli
2015/04/01 17:04:09
Done. TIL "echoes" :)
| |
167 URL echoBody = new URL(NativeTestServer.getEchoBodyURL()); | |
168 HttpURLConnection connection2 = | |
169 (HttpURLConnection) echoBody.openConnection(); | |
170 connection2.setDoOutput(true); | |
171 connection2.setRequestMethod("POST"); | |
172 assertEquals(200, connection2.getResponseCode()); | |
173 assertEquals("OK", connection2.getResponseMessage()); | |
174 assertEquals("", getResponseAsString(connection2)); | |
175 connection2.disconnect(); | |
176 } | |
177 | |
178 @SmallTest | |
179 @Feature({"Cronet"}) | |
180 @CompareDefaultWithCronet | |
181 public void testPostWithoutContentLength() throws Exception { | |
182 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
183 HttpURLConnection connection = | |
184 (HttpURLConnection) url.openConnection(); | |
185 connection.setDoOutput(true); | |
186 connection.setRequestMethod("POST"); | |
187 byte[] largeData = getLargeData(); | |
188 OutputStream out = connection.getOutputStream(); | |
189 int totalBytesWritten = 0; | |
190 // Number of bytes to write each time. It is doubled each time and is | |
191 // bigger than the internal buffer to make sure that the buffer grows. | |
192 int bytesToWrite = 2049; | |
193 while (totalBytesWritten < largeData.length) { | |
mmenke
2015/03/31 18:19:32
This loop should mirror testPostWithContentLength'
xunjieli
2015/04/01 17:04:09
Done.
| |
194 if (bytesToWrite > largeData.length - totalBytesWritten) { | |
195 // Do not write out of bound. | |
196 bytesToWrite = largeData.length - totalBytesWritten; | |
197 } | |
198 out.write(largeData, totalBytesWritten, bytesToWrite); | |
199 totalBytesWritten += bytesToWrite; | |
200 bytesToWrite *= 2; | |
201 } | |
202 assertEquals(200, connection.getResponseCode()); | |
203 assertEquals("OK", connection.getResponseMessage()); | |
204 checkLargeData(getResponseAsString(connection)); | |
205 connection.disconnect(); | |
206 } | |
207 | |
208 @SmallTest | |
209 @Feature({"Cronet"}) | |
210 @CompareDefaultWithCronet | |
211 public void testPostWithoutContentLengthOneMassiveWrite() throws Exception { | |
212 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
213 HttpURLConnection connection = | |
214 (HttpURLConnection) url.openConnection(); | |
215 connection.setDoOutput(true); | |
216 connection.setRequestMethod("POST"); | |
217 OutputStream out = connection.getOutputStream(); | |
218 byte[] largeData = getLargeData(); | |
219 out.write(largeData); | |
220 assertEquals(200, connection.getResponseCode()); | |
221 assertEquals("OK", connection.getResponseMessage()); | |
222 checkLargeData(getResponseAsString(connection)); | |
223 connection.disconnect(); | |
224 } | |
225 | |
226 @SmallTest | |
227 @Feature({"Cronet"}) | |
228 @CompareDefaultWithCronet | |
229 public void testPostWithoutContentLengthWriteOneByte() throws Exception { | |
230 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
231 HttpURLConnection connection = | |
232 (HttpURLConnection) url.openConnection(); | |
233 connection.setDoOutput(true); | |
234 connection.setRequestMethod("POST"); | |
235 OutputStream out = connection.getOutputStream(); | |
236 byte[] largeData = getLargeData(); | |
237 for (int i = 0; i < largeData.length; i++) { | |
238 out.write(largeData[i]); | |
239 } | |
240 assertEquals(200, connection.getResponseCode()); | |
241 assertEquals("OK", connection.getResponseMessage()); | |
242 checkLargeData(getResponseAsString(connection)); | |
243 connection.disconnect(); | |
244 } | |
245 | |
246 /** | |
247 * Tests write after connect. Strangely, the default implementation allows | |
248 * writing after being connected, so this test only runs against Cronet's | |
249 * implementation. | |
250 */ | |
251 @SmallTest | |
252 @Feature({"Cronet"}) | |
253 @OnlyRunCronetHttpURLConnection | |
254 public void testWriteAfterConnect() throws Exception { | |
255 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
256 HttpURLConnection connection = | |
257 (HttpURLConnection) url.openConnection(); | |
258 connection.setDoOutput(true); | |
259 connection.setRequestMethod("POST"); | |
260 OutputStream out = connection.getOutputStream(); | |
261 out.write(UPLOAD_DATA); | |
262 connection.connect(); | |
263 try { | |
264 // Attemp to write some more. | |
265 out.write(UPLOAD_DATA); | |
266 fail(); | |
267 } catch (IllegalStateException e) { | |
268 assertEquals("Cannot write after being connected.", e.getMessage()); | |
269 } | |
270 } | |
271 | |
272 /** | |
273 * Tests that if caller writes more than the content length provided, | |
274 * an exception should occur. | |
275 */ | |
276 @SmallTest | |
277 @Feature({"Cronet"}) | |
278 @CompareDefaultWithCronet | |
279 public void testWriteBufferOutOfBound() throws Exception { | |
280 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
281 HttpURLConnection connection = | |
282 (HttpURLConnection) url.openConnection(); | |
283 connection.setDoOutput(true); | |
284 connection.setRequestMethod("POST"); | |
285 // Use a content length that is 1 byte shorter than actual data. | |
286 connection.setRequestProperty("Content-Length", | |
287 Integer.toString(UPLOAD_DATA.length - 1)); | |
288 OutputStream out = connection.getOutputStream(); | |
289 // Write a few bytes first. | |
290 out.write(UPLOAD_DATA, 0, 3); | |
291 try { | |
292 // Write remaining bytes. | |
293 out.write(UPLOAD_DATA, 3, UPLOAD_DATA.length - 3); | |
294 fail(); | |
295 } catch (java.net.ProtocolException e) { | |
296 assertEquals("exceeded content-length limit of " | |
297 + (UPLOAD_DATA.length - 1) + " bytes", e.getMessage()); | |
298 } | |
299 } | |
300 | |
301 /** | |
302 * Same as {@code testWriteBufferOutOfBound()}, but it only writes one byte | |
303 * at a time. | |
304 */ | |
305 @SmallTest | |
306 @Feature({"Cronet"}) | |
307 @CompareDefaultWithCronet | |
308 public void testWriteBufferOutOfBoundWriteOneByte() throws Exception { | |
309 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
310 HttpURLConnection connection = | |
311 (HttpURLConnection) url.openConnection(); | |
312 connection.setDoOutput(true); | |
313 connection.setRequestMethod("POST"); | |
314 // Use a content length that is 1 byte shorter than actual data. | |
315 connection.setRequestProperty("Content-Length", | |
316 Integer.toString(UPLOAD_DATA.length - 1)); | |
317 OutputStream out = connection.getOutputStream(); | |
318 try { | |
319 for (int i = 0; i < UPLOAD_DATA.length; i++) { | |
320 out.write(UPLOAD_DATA[i]); | |
321 } | |
322 fail(); | |
323 } catch (java.net.ProtocolException e) { | |
324 assertEquals("exceeded content-length limit of " | |
325 + (UPLOAD_DATA.length - 1) + " bytes", e.getMessage()); | |
326 } | |
327 } | |
328 | |
329 /** | |
330 * Tests that {@link CronetBufferedOutputStream} supports rewind in a | |
331 * POST preserving redirect. | |
332 * Use {@code OnlyRunCronetHttpURLConnection} as the default implementation | |
333 * does not pass this test. | |
334 */ | |
335 @SmallTest | |
336 @Feature({"Cronet"}) | |
337 @OnlyRunCronetHttpURLConnection | |
338 public void testRewind() throws Exception { | |
339 URL url = new URL(NativeTestServer.getRedirectToEchoBody()); | |
340 HttpURLConnection connection = | |
341 (HttpURLConnection) url.openConnection(); | |
342 connection.setDoOutput(true); | |
343 connection.setRequestMethod("POST"); | |
344 connection.setRequestProperty("Content-Length", | |
345 Integer.toString(UPLOAD_DATA.length)); | |
346 OutputStream out = connection.getOutputStream(); | |
347 out.write(UPLOAD_DATA); | |
348 assertEquals(UPLOAD_DATA_STRING, getResponseAsString(connection)); | |
349 connection.disconnect(); | |
350 } | |
351 | |
352 /** | |
353 * Like {@link #testRewind} but does not set Content-Length header. | |
354 */ | |
355 @SmallTest | |
356 @Feature({"Cronet"}) | |
357 @OnlyRunCronetHttpURLConnection | |
358 public void testRewindWithoutContentLength() throws Exception { | |
359 URL url = new URL(NativeTestServer.getRedirectToEchoBody()); | |
360 HttpURLConnection connection = | |
361 (HttpURLConnection) url.openConnection(); | |
362 connection.setDoOutput(true); | |
363 connection.setRequestMethod("POST"); | |
364 OutputStream out = connection.getOutputStream(); | |
365 out.write(UPLOAD_DATA); | |
366 assertEquals(UPLOAD_DATA_STRING, getResponseAsString(connection)); | |
367 connection.disconnect(); | |
368 } | |
369 | |
370 /** | |
371 * Helper method to extract response body as a string for testing. | |
372 */ | |
373 private String getResponseAsString(HttpURLConnection connection) | |
374 throws Exception { | |
375 InputStream in = connection.getInputStream(); | |
376 ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
377 int b; | |
378 while ((b = in.read()) != -1) { | |
379 out.write(b); | |
380 } | |
381 return out.toString(); | |
382 } | |
383 | |
384 /** | |
385 * Produces a byte array that contains {@code REPEAT_COUNT} of | |
386 * {@code UPLOAD_DATA_STRING}. | |
387 */ | |
388 private byte[] getLargeData() { | |
389 byte[] largeData = new byte[REPEAT_COUNT * UPLOAD_DATA.length]; | |
390 for (int i = 0; i < REPEAT_COUNT; i++) { | |
391 for (int j = 0; j < UPLOAD_DATA.length; j++) { | |
392 largeData[i * UPLOAD_DATA.length + j] = UPLOAD_DATA[j]; | |
393 } | |
394 } | |
395 return largeData; | |
396 } | |
397 | |
398 /** | |
399 * Helper function to check whether {@code data} is a concatenation of | |
400 * {@code REPEAT_COUNT} {@code UPLOAD_DATA_STRING} strings. | |
401 */ | |
402 private void checkLargeData(String data) { | |
403 for (int i = 0; i < REPEAT_COUNT; i++) { | |
404 assertEquals(UPLOAD_DATA_STRING, data.substring( | |
405 UPLOAD_DATA_STRING.length() * i, | |
406 UPLOAD_DATA_STRING.length() * (i + 1))); | |
407 } | |
408 } | |
409 } | |
OLD | NEW |