Chromium Code Reviews| 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 import org.chromium.net.UploadDataSink; | |
| 15 import org.chromium.net.UrlRequestContext; | |
| 16 | |
| 17 import java.io.ByteArrayOutputStream; | |
| 18 import java.io.InputStream; | |
| 19 import java.io.OutputStream; | |
| 20 import java.net.HttpURLConnection; | |
| 21 import java.net.URL; | |
| 22 import java.nio.ByteBuffer; | |
| 23 import java.util.Arrays; | |
| 24 | |
| 25 /** | |
| 26 * Tests the CronetBufferedOutputStream implementation. | |
| 27 */ | |
| 28 public class CronetBufferedOutputStreamTest extends CronetTestBase { | |
| 29 private static final String UPLOAD_DATA_STRING = "Nifty upload data!"; | |
| 30 private static final byte[] UPLOAD_DATA = UPLOAD_DATA_STRING.getBytes(); | |
| 31 private static final int REPEAT_COUNT = 100000; | |
| 32 private CronetTestActivity mActivity; | |
| 33 private UrlRequestContext mUrlRequestContext; | |
| 34 | |
| 35 @Override | |
| 36 protected void setUp() throws Exception { | |
| 37 super.setUp(); | |
| 38 mActivity = launchCronetTestApp(); | |
| 39 mUrlRequestContext = mActivity.mUrlRequestContext; | |
| 40 assertTrue(NativeTestServer.startNativeTestServer( | |
| 41 getInstrumentation().getTargetContext())); | |
| 42 } | |
| 43 | |
| 44 @Override | |
| 45 protected void tearDown() throws Exception { | |
| 46 NativeTestServer.shutdownNativeTestServer(); | |
| 47 super.tearDown(); | |
| 48 } | |
| 49 | |
| 50 @SmallTest | |
| 51 @Feature({"Cronet"}) | |
| 52 @CompareDefaultWithCronet | |
| 53 public void testPostAfterConnectionMade() throws Exception { | |
| 54 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 55 HttpURLConnection connection = | |
| 56 (HttpURLConnection) url.openConnection(); | |
| 57 connection.setDoOutput(true); | |
| 58 connection.setRequestMethod("POST"); | |
| 59 assertEquals(200, connection.getResponseCode()); | |
| 60 try { | |
| 61 connection.getOutputStream(); | |
| 62 fail(); | |
| 63 } catch (java.net.ProtocolException e) { | |
| 64 // Expected. | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 @SmallTest | |
| 69 @Feature({"Cronet"}) | |
| 70 @CompareDefaultWithCronet | |
| 71 public void testPostWithContentLength() throws Exception { | |
| 72 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 73 HttpURLConnection connection = | |
| 74 (HttpURLConnection) url.openConnection(); | |
| 75 connection.setDoOutput(true); | |
| 76 connection.setRequestMethod("POST"); | |
| 77 connection.setRequestProperty("Content-Length", | |
| 78 Integer.toString(UPLOAD_DATA.length * REPEAT_COUNT)); | |
| 79 byte[] largeData = new byte[REPEAT_COUNT * UPLOAD_DATA.length]; | |
| 80 for (int i = 0; i < REPEAT_COUNT; i++) { | |
| 81 for (int j = 0; j < UPLOAD_DATA.length; j++) { | |
| 82 largeData[i * UPLOAD_DATA.length + j] = UPLOAD_DATA[j]; | |
| 83 } | |
| 84 } | |
| 85 OutputStream out = connection.getOutputStream(); | |
| 86 int totalBytesWritten = 0; | |
| 87 // Number of bytes to write each time. It is incremented by one from 0. | |
| 88 int bytesToWrite = 0; | |
| 89 while (totalBytesWritten < largeData.length) { | |
| 90 if (bytesToWrite > largeData.length - totalBytesWritten) { | |
| 91 // Do not write out of bound. | |
| 92 bytesToWrite = largeData.length - totalBytesWritten; | |
| 93 } | |
| 94 out.write(largeData, totalBytesWritten, bytesToWrite); | |
| 95 totalBytesWritten += bytesToWrite; | |
| 96 bytesToWrite++; | |
| 97 } | |
| 98 assertEquals(200, connection.getResponseCode()); | |
| 99 assertEquals("OK", connection.getResponseMessage()); | |
| 100 checkLargeData(getResponseAsString(connection)); | |
| 101 connection.disconnect(); | |
| 102 } | |
| 103 | |
| 104 @SmallTest | |
| 105 @Feature({"Cronet"}) | |
| 106 @CompareDefaultWithCronet | |
| 107 public void testPostWithContentLengthWriteOneByte() throws Exception { | |
| 108 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 109 HttpURLConnection connection = | |
| 110 (HttpURLConnection) url.openConnection(); | |
| 111 connection.setDoOutput(true); | |
| 112 connection.setRequestMethod("POST"); | |
| 113 connection.setRequestProperty("Content-Length", | |
| 114 Integer.toString(UPLOAD_DATA.length * REPEAT_COUNT)); | |
| 115 OutputStream out = connection.getOutputStream(); | |
| 116 for (int i = 0; i < REPEAT_COUNT; i++) { | |
| 117 for (int j = 0; j < UPLOAD_DATA.length; j++) { | |
| 118 // Write one byte at a time. | |
| 119 out.write(UPLOAD_DATA[j]); | |
| 120 } | |
| 121 } | |
| 122 assertEquals(200, connection.getResponseCode()); | |
| 123 assertEquals("OK", connection.getResponseMessage()); | |
| 124 checkLargeData(getResponseAsString(connection)); | |
| 125 connection.disconnect(); | |
| 126 } | |
| 127 | |
| 128 @SmallTest | |
| 129 @Feature({"Cronet"}) | |
| 130 @CompareDefaultWithCronet | |
| 131 public void testPostWithZeroContentLength() throws Exception { | |
|
mmenke
2015/03/25 18:34:57
Maybe a zero length upload without a content lengt
xunjieli
2015/03/27 17:46:45
Done.
| |
| 132 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 133 HttpURLConnection connection = | |
| 134 (HttpURLConnection) url.openConnection(); | |
| 135 connection.setDoOutput(true); | |
| 136 connection.setRequestMethod("POST"); | |
| 137 connection.setRequestProperty("Content-Length", "0"); | |
| 138 assertEquals(200, connection.getResponseCode()); | |
| 139 assertEquals("OK", connection.getResponseMessage()); | |
| 140 assertEquals("", getResponseAsString(connection)); | |
| 141 connection.disconnect(); | |
| 142 } | |
| 143 | |
| 144 @SmallTest | |
| 145 @Feature({"Cronet"}) | |
| 146 @CompareDefaultWithCronet | |
| 147 public void testPostWithoutContentLength() throws Exception { | |
| 148 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 149 HttpURLConnection connection = | |
| 150 (HttpURLConnection) url.openConnection(); | |
| 151 connection.setDoOutput(true); | |
| 152 connection.setRequestMethod("POST"); | |
| 153 OutputStream out = connection.getOutputStream(); | |
| 154 for (int i = 0; i < REPEAT_COUNT; i++) { | |
| 155 out.write(UPLOAD_DATA); | |
| 156 } | |
| 157 assertEquals(200, connection.getResponseCode()); | |
| 158 assertEquals("OK", connection.getResponseMessage()); | |
| 159 checkLargeData(getResponseAsString(connection)); | |
| 160 connection.disconnect(); | |
| 161 } | |
| 162 | |
| 163 /** | |
| 164 * Tests that if caller writes more than the content length provided, | |
| 165 * an exception should occur. | |
| 166 */ | |
| 167 @SmallTest | |
| 168 @Feature({"Cronet"}) | |
| 169 @CompareDefaultWithCronet | |
| 170 public void testWriteBufferOutOfBound() throws Exception { | |
| 171 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 172 HttpURLConnection connection = | |
| 173 (HttpURLConnection) url.openConnection(); | |
| 174 connection.setDoOutput(true); | |
| 175 connection.setRequestMethod("POST"); | |
| 176 // Use a content length that is 1 byte shorter than actual data. | |
| 177 connection.setRequestProperty("Content-Length", | |
| 178 Integer.toString(UPLOAD_DATA.length - 1)); | |
| 179 OutputStream out = connection.getOutputStream(); | |
| 180 try { | |
| 181 out.write(UPLOAD_DATA); | |
|
mmenke
2015/03/25 18:34:57
Suggest a test like this that does two writes.
xunjieli
2015/03/27 17:46:45
Done.
| |
| 182 fail(); | |
| 183 } catch (java.net.ProtocolException e) { | |
| 184 assertEquals("exceeded content-length limit of " | |
| 185 + (UPLOAD_DATA.length - 1) + " bytes", e.getMessage()); | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 /** | |
| 190 * Same as {@code testWriteBufferOutOfBound()}, but it only writes one byte | |
| 191 * at a time. | |
| 192 */ | |
| 193 @SmallTest | |
| 194 @Feature({"Cronet"}) | |
| 195 @CompareDefaultWithCronet | |
| 196 public void testWriteBufferOutOfBoundWriteOneByte() throws Exception { | |
| 197 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 198 HttpURLConnection connection = | |
| 199 (HttpURLConnection) url.openConnection(); | |
| 200 connection.setDoOutput(true); | |
| 201 connection.setRequestMethod("POST"); | |
| 202 // Use a content length that is 1 byte shorter than actual data. | |
| 203 connection.setRequestProperty("Content-Length", | |
| 204 Integer.toString(UPLOAD_DATA.length - 1)); | |
| 205 OutputStream out = connection.getOutputStream(); | |
| 206 try { | |
| 207 for (int i = 0; i < UPLOAD_DATA.length; i++) { | |
| 208 out.write(UPLOAD_DATA[i]); | |
| 209 } | |
| 210 fail(); | |
| 211 } catch (java.net.ProtocolException e) { | |
| 212 assertEquals("exceeded content-length limit of " | |
| 213 + (UPLOAD_DATA.length - 1) + " bytes", e.getMessage()); | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 /** | |
| 218 * Tests that {@link CronetBufferedOutputStream} supports rewind. | |
| 219 */ | |
| 220 @SmallTest | |
| 221 @Feature({"Cronet"}) | |
| 222 @OnlyRunCronetHttpURLConnection | |
| 223 public void testRewind() throws Exception { | |
| 224 URL url = new URL(NativeTestServer.getEchoBodyURL()); | |
| 225 CronetHttpURLConnection conn = new CronetHttpURLConnection(url, | |
| 226 mUrlRequestContext); | |
| 227 CronetBufferedOutputStream out = | |
| 228 new CronetBufferedOutputStream(conn, UPLOAD_DATA.length); | |
| 229 out.write(UPLOAD_DATA); | |
| 230 TestUploadDataSink sink = new TestUploadDataSink(); | |
| 231 out.rewind(sink); | |
| 232 assertTrue(sink.mRewindSucceededCalled); | |
| 233 ByteBuffer byteBuffer = ByteBuffer.allocate(UPLOAD_DATA.length); | |
| 234 out.read(sink, byteBuffer); | |
| 235 assertTrue(sink.mReadSucceededCalled); | |
| 236 assertTrue(Arrays.equals(UPLOAD_DATA, byteBuffer.array())); | |
|
mmenke
2015/03/25 18:34:57
Rather than doing all this manually, can we just u
xunjieli
2015/03/27 17:46:45
Done. Good idea! But the default implementation re
| |
| 237 } | |
| 238 | |
| 239 private static class TestUploadDataSink implements UploadDataSink { | |
| 240 boolean mReadSucceededCalled = false; | |
| 241 boolean mRewindSucceededCalled = false; | |
| 242 | |
| 243 @Override | |
| 244 public void onReadSucceeded(boolean finalChunk) { | |
| 245 mReadSucceededCalled = true; | |
| 246 } | |
| 247 | |
| 248 @Override | |
| 249 public void onReadError(Exception exception) { | |
| 250 // Left blank. | |
| 251 } | |
| 252 | |
| 253 @Override | |
| 254 public void onRewindSucceeded() { | |
| 255 mRewindSucceededCalled = true; | |
| 256 } | |
| 257 | |
| 258 @Override | |
| 259 public void onRewindError(Exception e) { | |
| 260 // Left blank. | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 /** | |
| 265 * Helper method to extract response body as a string for testing. | |
| 266 */ | |
| 267 private String getResponseAsString(HttpURLConnection connection) | |
| 268 throws Exception { | |
| 269 InputStream in = connection.getInputStream(); | |
| 270 ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
| 271 int b; | |
| 272 while ((b = in.read()) != -1) { | |
| 273 out.write(b); | |
| 274 } | |
| 275 return out.toString(); | |
| 276 } | |
| 277 | |
| 278 /** | |
| 279 * Helper function to check whether {@code data} is a concatenation of | |
| 280 * {@code REPEAT_COUNT} {@code UPLOAD_DATA_STRING} strings. | |
| 281 */ | |
| 282 private void checkLargeData(String data) { | |
| 283 for (int i = 0; i < REPEAT_COUNT; i++) { | |
| 284 assertEquals(UPLOAD_DATA_STRING, data.substring( | |
| 285 UPLOAD_DATA_STRING.length() * i, | |
| 286 UPLOAD_DATA_STRING.length() * (i + 1))); | |
| 287 } | |
| 288 } | |
| 289 } | |
| OLD | NEW |