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

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

Issue 1412243012: Initial implementation of CronetBidirectionalStream. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Helen's comments. Created 4 years, 11 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 2015 The Chromium Authors. All rights reserved. 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 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.os.ConditionVariable;
7 import android.test.suitebuilder.annotation.SmallTest; 8 import android.test.suitebuilder.annotation.SmallTest;
8 9
9 import org.chromium.base.test.util.Feature; 10 import org.chromium.base.test.util.Feature;
11 import org.chromium.net.TestBidirectionalStreamCallback.FailureType;
12 import org.chromium.net.TestBidirectionalStreamCallback.ResponseStep;
10 13
11 import java.nio.ByteBuffer; 14 import java.nio.ByteBuffer;
12 import java.util.concurrent.Executor; 15 import java.util.ArrayList;
13 import java.util.concurrent.ExecutorService; 16 import java.util.List;
14 import java.util.concurrent.Executors; 17 import java.util.regex.Matcher;
15 import java.util.concurrent.ThreadFactory; 18 import java.util.regex.Pattern;
16
17 /** 19 /**
18 * Test functionality of BidirectionalStream interface. 20 * Test functionality of BidirectionalStream interface.
19 */ 21 */
20 public class BidirectionalStreamTest extends CronetTestBase { 22 public class BidirectionalStreamTest extends CronetTestBase {
23 private static final String CERT_USED = "quic_test.example.com.crt";
24 private static final String KEY_USED = "quic_test.example.com.key";
25 private static final String[] CERTS_USED = {CERT_USED};
26
21 private CronetTestFramework mTestFramework; 27 private CronetTestFramework mTestFramework;
28 // URL used for base tests.
29 private static final String TEST_URL = "https://127.0.0.1:8443";
22 30
23 @Override 31 @Override
24 protected void setUp() throws Exception { 32 protected void setUp() throws Exception {
25 super.setUp(); 33 super.setUp();
26 mTestFramework = startCronetTestFramework(); 34 // Load library first to create MockCertVerifier.
35 System.loadLibrary("cronet_tests");
36
37 CronetEngine.Builder builder = new CronetEngine.Builder(getContext());
38 builder.setMockCertVerifierForTesting(MockCertVerifier.createMockCertVer ifier(CERTS_USED));
39
40 mTestFramework = startCronetTestFrameworkWithUrlAndCronetEngineBuilder(n ull, builder);
27 assertTrue(NativeTestServer.startNativeTestServer(getContext())); 41 assertTrue(NativeTestServer.startNativeTestServer(getContext()));
42 assertTrue(Http2TestServer.startHttp2TestServer(getContext(), CERT_USED, KEY_USED));
pauljensen 2016/01/04 19:56:00 Hmm so will Andrei's work add Http2TestServer?
mef 2016/01/04 22:27:08 It is added in my CL https://codereview.chromium.o
28 // Add url interceptors after native application context is initialized. 43 // Add url interceptors after native application context is initialized.
29 MockUrlRequestJobFactory.setUp(); 44 MockUrlRequestJobFactory.setUp();
30 } 45 }
31 46
32 @Override 47 @Override
33 protected void tearDown() throws Exception { 48 protected void tearDown() throws Exception {
49 Http2TestServer.shutdownHttp2TestServer();
34 NativeTestServer.shutdownNativeTestServer(); 50 NativeTestServer.shutdownNativeTestServer();
35 mTestFramework.mCronetEngine.shutdown(); 51 if (mTestFramework.mCronetEngine != null) mTestFramework.mCronetEngine.s hutdown();
36 super.tearDown(); 52 super.tearDown();
37 } 53 }
38 54
39 private class TestBidirectionalStreamCallback extends BidirectionalStream.Ca llback { 55 private TestBidirectionalStreamCallback startAndWaitForComplete(String url) throws Exception {
40 // Executor Service for Cronet callbacks. 56 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
41 private final ExecutorService mExecutorService =
42 Executors.newSingleThreadExecutor(new ExecutorThreadFactory());
43 private Thread mExecutorThread;
44 57
45 private class ExecutorThreadFactory implements ThreadFactory { 58 // Create stream.
46 public Thread newThread(Runnable r) { 59 BidirectionalStream stream =
47 mExecutorThread = new Thread(r); 60 new BidirectionalStream.Builder(url, callback, callback.getExecu tor(),
48 return mExecutorThread; 61 mTestFramework.mCronetEngine)
49 } 62 .setHttpMethod("GET")
63 .build();
64 stream.start();
65 callback.blockForDone();
66 assertTrue(stream.isDone());
67 return callback;
68 }
69
70 private void checkResponseInfo(UrlResponseInfo responseInfo, String expected Url,
71 int expectedHttpStatusCode, String expectedHttpStatusText) {
72 assertEquals(expectedUrl, responseInfo.getUrl());
73 assertEquals(
74 expectedUrl, responseInfo.getUrlChain().get(responseInfo.getUrlC hain().size() - 1));
75 assertEquals(expectedHttpStatusCode, responseInfo.getHttpStatusCode());
76 assertEquals(expectedHttpStatusText, responseInfo.getHttpStatusText());
77 assertFalse(responseInfo.wasCached());
78 assertTrue(responseInfo.toString().length() > 0);
79 }
80
81 private static String makeLongString(String base, int repetition) {
82 StringBuilder builder = new StringBuilder(base.length() * repetition);
83 for (int i = 0; i < repetition; ++i) {
84 builder.append(i);
85 builder.append(base);
50 } 86 }
51 87 return builder.toString();
52 @Override
53 public void onRequestHeadersSent(BidirectionalStream stream) {}
54
55 @Override
56 public void onResponseHeadersReceived(BidirectionalStream stream, UrlRes ponseInfo info) {}
57
58 @Override
59 public void onReadCompleted(
60 BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buf fer) {}
61
62 @Override
63 public void onWriteCompleted(
64 BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buf fer) {}
65
66 @Override
67 public void onResponseTrailersReceived(BidirectionalStream stream, UrlRe sponseInfo info,
68 UrlResponseInfo.HeaderBlock trailers) {}
69
70 @Override
71 public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info ) {}
72
73 @Override
74 public void onFailed(
75 BidirectionalStream stream, UrlResponseInfo info, CronetExceptio n error) {}
76
77 @Override
78 public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) {}
79
80 Executor getExecutor() {
81 return mExecutorService;
82 }
83 } 88 }
84 89
85 @SmallTest 90 @SmallTest
86 @Feature({"Cronet"}) 91 @Feature({"Cronet"})
87 public void testBuilderChecks() throws Exception { 92 public void testBuilderChecks() throws Exception {
88 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback(); 93 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
89 try { 94 try {
90 new BidirectionalStream.Builder( 95 new BidirectionalStream.Builder(
91 null, callback, callback.getExecutor(), mTestFramework.mCron etEngine); 96 null, callback, callback.getExecutor(), mTestFramework.mCron etEngine);
92 fail("URL not null-checked"); 97 fail("URL not null-checked");
(...skipping 18 matching lines...) Expand all
111 new BidirectionalStream.Builder( 116 new BidirectionalStream.Builder(
112 NativeTestServer.getRedirectURL(), callback, callback.getExe cutor(), null); 117 NativeTestServer.getRedirectURL(), callback, callback.getExe cutor(), null);
113 fail("CronetEngine not null-checked"); 118 fail("CronetEngine not null-checked");
114 } catch (NullPointerException e) { 119 } catch (NullPointerException e) {
115 assertEquals("CronetEngine is required.", e.getMessage()); 120 assertEquals("CronetEngine is required.", e.getMessage());
116 } 121 }
117 // Verify successful creation doesn't throw. 122 // Verify successful creation doesn't throw.
118 new BidirectionalStream.Builder(NativeTestServer.getRedirectURL(), callb ack, 123 new BidirectionalStream.Builder(NativeTestServer.getRedirectURL(), callb ack,
119 callback.getExecutor(), mTestFramework.mCronetEngine); 124 callback.getExecutor(), mTestFramework.mCronetEngine);
120 } 125 }
126
127 @SmallTest
128 @Feature({"Cronet"})
129 public void testFailPlainHttp() throws Exception {
130 String url = NativeTestServer.getEchoMethodURL();
131 TestBidirectionalStreamCallback callback = startAndWaitForComplete(url);
132 assertEquals("Exception in BidirectionalStream: net::ERR_DISALLOWED_URL_ SCHEME",
133 callback.mError.getMessage());
134 }
135
136 @SmallTest
137 @Feature({"Cronet"})
138 public void testSimpleGet() throws Exception {
139 String url = Http2TestServer.getEchoMethodUrl();
140 TestBidirectionalStreamCallback callback = startAndWaitForComplete(url);
141 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
142 // Default method is 'GET'.
143 assertEquals("GET", callback.mResponseAsString);
144 assertEquals(String.format("UrlResponseInfo[%s]: urlChain = [%s], httpSt atus = 200 , "
145 + "headers = [:status=200], wasCached = fal se, "
146 + "negotiatedProtocol = h2, proxyServer= nu ll, "
147 + "receivedBytesCount = 27",
148 url, url),
149 callback.mResponseInfo.toString());
150 checkResponseInfo(callback.mResponseInfo, Http2TestServer.getEchoMethodU rl(), 200, "");
151 }
152
153 @SmallTest
154 @Feature({"Cronet"})
155 public void testSimpleHead() throws Exception {
156 String url = Http2TestServer.getEchoMethodUrl();
157 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
158
159 // Create stream.
160 BidirectionalStream stream =
161 new BidirectionalStream.Builder(url, callback, callback.getExecu tor(),
162 mTestFramework.mCronetEngine)
163 .setHttpMethod("HEAD")
164 .build();
165 stream.start();
166 callback.blockForDone();
167 assertTrue(stream.isDone());
168 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
169 assertEquals("HEAD", callback.mResponseAsString);
170 assertEquals(String.format("UrlResponseInfo[%s]: urlChain = [%s], httpSt atus = 200 , "
171 + "headers = [:status=200], wasCached = fal se, "
172 + "negotiatedProtocol = h2, proxyServer= nu ll, "
173 + "receivedBytesCount = 28",
174 url, url),
175 callback.mResponseInfo.toString());
176 checkResponseInfo(callback.mResponseInfo, Http2TestServer.getEchoMethodU rl(), 200, "");
177 }
178
179 @SmallTest
180 @Feature({"Cronet"})
181 public void testSimplePost() throws Exception {
182 String url = Http2TestServer.getBaseUrl();
183 mTestFramework.startNetLog();
184
185 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
186 callback.addWriteData("Test String".getBytes());
187 callback.addWriteData("1234567890".getBytes());
188 callback.addWriteData("woot!".getBytes());
189
190 // Create stream.
191 BidirectionalStream stream =
192 new BidirectionalStream.Builder(url, callback, callback.getExecu tor(),
193 mTestFramework.mCronetEngine)
194 .addHeader("foo", "bar")
195 .addHeader("Content-Type", "zebra")
196 .build();
197 stream.start();
198 callback.blockForDone();
199 assertTrue(stream.isDone());
200
201 mTestFramework.stopNetLog();
202
203 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
204 assertEquals("woot!", callback.mResponseAsString);
205 }
206
207 @SmallTest
208 @Feature({"Cronet"})
209 public void testSetHttpMethod() throws Exception {
210 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
211 callback.addWriteData("Put This Data!".getBytes());
212
213 String methodName = "PUT";
214 BidirectionalStream.Builder builder = new BidirectionalStream.Builder(
215 TEST_URL, callback, callback.getExecutor(), mTestFramework.mCron etEngine);
216 // Try to set 'null' method.
217 try {
218 builder.setHttpMethod(null);
219 fail("Exception not thrown");
220 } catch (NullPointerException e) {
221 assertEquals("Method is required.", e.getMessage());
222 }
223
224 builder.setHttpMethod(methodName);
225 builder.build().start();
226 callback.blockForDone();
227 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
228 assertEquals("Put This Data!", callback.mResponseAsString);
229 }
230
231 @SmallTest
232 @Feature({"Cronet"})
233 public void testBadMethod() throws Exception {
234 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
235 BidirectionalStream.Builder builder = new BidirectionalStream.Builder(
236 TEST_URL, callback, callback.getExecutor(), mTestFramework.mCron etEngine);
237 try {
238 builder.setHttpMethod("bad:method!");
239 builder.build().start();
240 fail("IllegalArgumentException not thrown.");
241 } catch (IllegalArgumentException e) {
242 assertEquals("Invalid http method bad:method!", e.getMessage());
243 }
244 }
245
246 @SmallTest
247 @Feature({"Cronet"})
248 public void testBadHeaderName() throws Exception {
249 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
250 BidirectionalStream.Builder builder = new BidirectionalStream.Builder(
251 TEST_URL, callback, callback.getExecutor(), mTestFramework.mCron etEngine);
252 try {
253 builder.addHeader("header:name", "headervalue");
254 builder.build().start();
255 fail("IllegalArgumentException not thrown.");
256 } catch (IllegalArgumentException e) {
257 assertEquals("Invalid header header:name=headervalue", e.getMessage( ));
258 }
259 }
260
261 @SmallTest
262 @Feature({"Cronet"})
263 public void testBadHeaderValue() throws Exception {
264 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
265 BidirectionalStream.Builder builder = new BidirectionalStream.Builder(
266 TEST_URL, callback, callback.getExecutor(), mTestFramework.mCron etEngine);
267 try {
268 builder.addHeader("headername", "bad header\r\nvalue");
269 builder.build().start();
270 fail("IllegalArgumentException not thrown.");
271 } catch (IllegalArgumentException e) {
272 assertEquals("Invalid header headername=bad header\r\nvalue", e.getM essage());
273 }
274 }
275
276 @SmallTest
277 @Feature({"Cronet"})
278 public void testAddHeader() throws Exception {
279 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
280 String headerName = "header-name";
281 String headerValue = "header-value";
282 BidirectionalStream.Builder builder =
283 new BidirectionalStream.Builder(Http2TestServer.getEchoHeaderUrl (headerName),
284 callback, callback.getExecutor(), mTestFramework.mCronet Engine);
285
286 builder.addHeader(headerName, headerValue);
287 builder.setHttpMethod("GET");
288 builder.build().start();
289 callback.blockForDone();
290 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
291 assertEquals(headerValue, callback.mResponseAsString);
292 }
293
294 @SmallTest
295 @Feature({"Cronet"})
296 public void testMultiRequestHeaders() throws Exception {
297 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
298 String headerName = "header-name";
299 String headerValue1 = "header-value1";
300 String headerValue2 = "header-value2";
301 BidirectionalStream.Builder builder =
302 new BidirectionalStream.Builder(Http2TestServer.getEchoAllHeader sUrl(), callback,
303 callback.getExecutor(), mTestFramework.mCronetEngine);
304 builder.addHeader(headerName, headerValue1);
305 builder.addHeader(headerName, headerValue2);
306 builder.setHttpMethod("GET");
307 builder.build().start();
308 callback.blockForDone();
309 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
310 String headers = callback.mResponseAsString;
311 Pattern pattern = Pattern.compile(headerName + ":\\s(.*)\\r\\n");
312 Matcher matcher = pattern.matcher(headers);
313 List<String> actualValues = new ArrayList<String>();
314 while (matcher.find()) {
315 actualValues.add(matcher.group(1));
316 }
317 assertEquals(1, actualValues.size());
318 assertEquals("header-value2", actualValues.get(0));
319 }
320
321 @SmallTest
322 @Feature({"Cronet"})
323 public void testEchoTrailers() throws Exception {
324 mTestFramework.startNetLog();
325
326 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
327 String headerName = "header-name";
328 String headerValue = "header-value";
329 BidirectionalStream.Builder builder =
330 new BidirectionalStream.Builder(Http2TestServer.getEchoTrailersU rl(), callback,
331 callback.getExecutor(), mTestFramework.mCronetEngine);
332 builder.addHeader(headerName, headerValue);
333 builder.setHttpMethod("GET");
334 builder.build().start();
335 callback.blockForDone();
336 mTestFramework.stopNetLog();
337
338 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
339 assertNotNull(callback.mTrailers);
340 assertEquals(headerValue, callback.mTrailers.getAsMap().get(headerName). get(0));
341 }
342
343 @SmallTest
344 @Feature({"Cronet"})
345 public void testCustomUserAgent() throws Exception {
346 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
347 String userAgentName = "User-Agent";
348 String userAgentValue = "User-Agent-Value";
349 BidirectionalStream.Builder builder =
350 new BidirectionalStream.Builder(Http2TestServer.getEchoHeaderUrl (userAgentName),
351 callback, callback.getExecutor(), mTestFramework.mCronet Engine);
352 builder.setHttpMethod("GET");
353 builder.addHeader(userAgentName, userAgentValue);
354 builder.build().start();
355 callback.blockForDone();
356 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
357 assertEquals(userAgentValue, callback.mResponseAsString);
358 }
359
360 @SmallTest
361 @Feature({"Cronet"})
362 public void testEchoStream() throws Exception {
363 String url = Http2TestServer.getEchoStreamUrl();
364 mTestFramework.startNetLog();
365
366 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
367 String[] testData = {"Test String", makeLongString("1234567890", 50000), "woot!"};
368 StringBuilder stringData = new StringBuilder();
369 for (String writeData : testData) {
370 callback.addWriteData(writeData.getBytes());
371 stringData.append(writeData);
372 }
373
374 // Create stream.
375 BidirectionalStream stream =
376 new BidirectionalStream.Builder(url, callback, callback.getExecu tor(),
377 mTestFramework.mCronetEngine)
378 .addHeader("foo", "Value with Spaces")
379 .addHeader("Content-Type", "zebra")
380 .build();
381 stream.start();
382 callback.blockForDone();
383 assertTrue(stream.isDone());
384
385 mTestFramework.stopNetLog();
386
387 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
388 assertEquals(stringData.toString(), callback.mResponseAsString);
389 assertEquals("Value with Spaces", callback.mResponseInfo.getAllHeaders() .get("foo").get(0));
390 assertEquals("zebra", callback.mResponseInfo.getAllHeaders().get("Conten t-Type").get(0));
391 }
392
393 /**
394 * Checks that the buffer is updated correctly, when starting at an offset.
395 */
396 @SmallTest
397 @Feature({"Cronet"})
398 public void testSimpleGetBufferUpdates() throws Exception {
399 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
400 callback.setAutoAdvance(false);
401 // Since themethod is "GET", the expected response body is also "GET".
402 BidirectionalStream.Builder builder =
403 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
404 callback.getExecutor(), mTestFramework.mCronetEngine);
405 BidirectionalStream stream = builder.setHttpMethod("GET").build();
406 stream.start();
407 callback.waitForNextReadStep();
408
409 assertEquals(null, callback.mError);
410 assertFalse(callback.isDone());
411 assertEquals(TestBidirectionalStreamCallback.ResponseStep.ON_RESPONSE_ST ARTED,
412 callback.mResponseStep);
413
414 ByteBuffer readBuffer = ByteBuffer.allocateDirect(5);
415 readBuffer.put("FOR".getBytes());
416 assertEquals(3, readBuffer.position());
417
418 // Read first two characters of the response ("GE"). It's theoretically
419 // possible to need one read per character, though in practice,
420 // shouldn't happen.
421 while (callback.mResponseAsString.length() < 2) {
422 assertFalse(callback.isDone());
423 callback.startNextRead(stream, readBuffer);
424 callback.waitForNextReadStep();
425 }
426
427 // Make sure the two characters were read.
428 assertEquals("GE", callback.mResponseAsString);
429
430 // Check the contents of the entire buffer. The first 3 characters
431 // should not have been changed, and the last two should be the first
432 // two characters from the response.
433 assertEquals("FORGE", bufferContentsToString(readBuffer, 0, 5));
434 // The limit and position should be 5.
435 assertEquals(5, readBuffer.limit());
436 assertEquals(5, readBuffer.position());
437
438 assertEquals(ResponseStep.ON_READ_COMPLETED, callback.mResponseStep);
439
440 // Start reading from position 3. Since the only remaining character
441 // from the response is a "T", when the read completes, the buffer
442 // should contain "FORTE", with a position() of 4 and a limit() of 5.
443 readBuffer.position(3);
444 callback.startNextRead(stream, readBuffer);
445 callback.waitForNextReadStep();
446
447 // Make sure all three characters of the response have now been read.
448 assertEquals("GET", callback.mResponseAsString);
449
450 // Check the entire contents of the buffer. Only the third character
451 // should have been modified.
452 assertEquals("FORTE", bufferContentsToString(readBuffer, 0, 5));
453
454 // Make sure position and limit were updated correctly.
455 assertEquals(4, readBuffer.position());
456 assertEquals(5, readBuffer.limit());
457
458 assertEquals(ResponseStep.ON_READ_COMPLETED, callback.mResponseStep);
459
460 // One more read attempt. The request should complete.
461 readBuffer.position(1);
462 readBuffer.limit(5);
463 callback.startNextRead(stream, readBuffer);
464 callback.waitForNextReadStep();
465
466 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
467 assertEquals("GET", callback.mResponseAsString);
468 checkResponseInfo(callback.mResponseInfo, Http2TestServer.getEchoMethodU rl(), 200, "");
469
470 // Check that buffer contents were not modified.
471 assertEquals("FORTE", bufferContentsToString(readBuffer, 0, 5));
472
473 // Position should not have been modified, since nothing was read.
474 assertEquals(1, readBuffer.position());
475 // Limit should be unchanged as always.
476 assertEquals(5, readBuffer.limit());
477
478 assertEquals(ResponseStep.ON_SUCCEEDED, callback.mResponseStep);
479
480 // Make sure there are no other pending messages, which would trigger
481 // asserts in TestBidirectionalCallback.
482 testSimpleGet();
483 }
484
485 @SmallTest
486 @Feature({"Cronet"})
487 public void testBadBuffers() throws Exception {
488 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
489 callback.setAutoAdvance(false);
490 BidirectionalStream.Builder builder =
491 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
492 callback.getExecutor(), mTestFramework.mCronetEngine);
493 BidirectionalStream stream = builder.setHttpMethod("GET").build();
494 stream.start();
495 callback.waitForNextReadStep();
496
497 assertEquals(null, callback.mError);
498 assertFalse(callback.isDone());
499 assertEquals(TestBidirectionalStreamCallback.ResponseStep.ON_RESPONSE_ST ARTED,
500 callback.mResponseStep);
501
502 // Try to read using a full buffer.
503 try {
504 ByteBuffer readBuffer = ByteBuffer.allocateDirect(4);
505 readBuffer.put("full".getBytes());
506 stream.read(readBuffer);
507 fail("Exception not thrown");
508 } catch (IllegalArgumentException e) {
509 assertEquals("ByteBuffer is already full.", e.getMessage());
510 }
511
512 // Try to read using a non-direct buffer.
513 try {
514 ByteBuffer readBuffer = ByteBuffer.allocate(5);
515 stream.read(readBuffer);
516 fail("Exception not thrown");
517 } catch (Exception e) {
518 assertEquals("byteBuffer must be a direct ByteBuffer.", e.getMessage ());
519 }
520
521 // Finish the stream with a direct ByteBuffer.
522 callback.setAutoAdvance(true);
523 ByteBuffer readBuffer = ByteBuffer.allocateDirect(5);
524 stream.read(readBuffer);
525 callback.blockForDone();
526 assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
527 assertEquals("GET", callback.mResponseAsString);
528 }
529
530 private void throwOrCancel(FailureType failureType, ResponseStep failureStep ,
531 boolean expectResponseInfo, boolean expectError) {
532 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
533 callback.setFailure(failureType, failureStep);
534 BidirectionalStream.Builder builder =
535 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
536 callback.getExecutor(), mTestFramework.mCronetEngine);
537 BidirectionalStream stream = builder.setHttpMethod("GET").build();
538 stream.start();
539 callback.blockForDone();
540 assertEquals(callback.mResponseStep, failureStep);
541 assertTrue(stream.isDone());
542 assertEquals(expectResponseInfo, callback.mResponseInfo != null);
543 assertEquals(expectError, callback.mError != null);
544 assertEquals(expectError, callback.mOnErrorCalled);
545 assertEquals(failureType == FailureType.CANCEL_SYNC
546 || failureType == FailureType.CANCEL_ASYNC
547 || failureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE ,
548 callback.mOnCanceledCalled);
549 }
550
551 @SmallTest
552 @Feature({"Cronet"})
553 public void testFailures() throws Exception {
554 throwOrCancel(FailureType.CANCEL_SYNC, ResponseStep.ON_REQUEST_HEADERS_S ENT, false, false);
555 throwOrCancel(FailureType.CANCEL_ASYNC, ResponseStep.ON_REQUEST_HEADERS_ SENT, false, false);
556 throwOrCancel(FailureType.CANCEL_ASYNC_WITHOUT_PAUSE, ResponseStep.ON_RE QUEST_HEADERS_SENT,
557 false, false);
558 throwOrCancel(FailureType.THROW_SYNC, ResponseStep.ON_REQUEST_HEADERS_SE NT, false, true);
559
560 throwOrCancel(FailureType.CANCEL_SYNC, ResponseStep.ON_RESPONSE_STARTED, true, false);
561 throwOrCancel(FailureType.CANCEL_ASYNC, ResponseStep.ON_RESPONSE_STARTED , true, false);
562 throwOrCancel(FailureType.CANCEL_ASYNC_WITHOUT_PAUSE, ResponseStep.ON_RE SPONSE_STARTED,
563 true, false);
564 throwOrCancel(FailureType.THROW_SYNC, ResponseStep.ON_RESPONSE_STARTED, true, true);
565
566 throwOrCancel(FailureType.CANCEL_SYNC, ResponseStep.ON_READ_COMPLETED, t rue, false);
567 throwOrCancel(FailureType.CANCEL_ASYNC, ResponseStep.ON_READ_COMPLETED, true, false);
568 throwOrCancel(FailureType.CANCEL_ASYNC_WITHOUT_PAUSE, ResponseStep.ON_RE AD_COMPLETED, true,
569 false);
570 throwOrCancel(FailureType.THROW_SYNC, ResponseStep.ON_READ_COMPLETED, tr ue, true);
571 }
572
573 @SmallTest
574 @Feature({"Cronet"})
575 public void testThrowOnSucceeded() {
576 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
577 callback.setFailure(FailureType.THROW_SYNC, ResponseStep.ON_SUCCEEDED);
578 BidirectionalStream.Builder builder =
579 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
580 callback.getExecutor(), mTestFramework.mCronetEngine);
581 BidirectionalStream stream = builder.setHttpMethod("GET").build();
582 stream.start();
583 callback.blockForDone();
584 assertEquals(callback.mResponseStep, ResponseStep.ON_SUCCEEDED);
585 assertTrue(stream.isDone());
586 assertNotNull(callback.mResponseInfo);
587 assertNull(callback.mError);
588 assertFalse(callback.mOnErrorCalled);
589 }
590
591 @SmallTest
592 @Feature({"Cronet"})
593 public void testExecutorShutdown() {
594 TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCa llback();
595
596 callback.setAutoAdvance(false);
597 BidirectionalStream.Builder builder =
598 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
599 callback.getExecutor(), mTestFramework.mCronetEngine);
600 CronetBidirectionalStream stream =
601 (CronetBidirectionalStream) builder.setHttpMethod("GET").build() ;
602 stream.start();
603 callback.waitForNextReadStep();
604 assertFalse(callback.isDone());
605 assertFalse(stream.isDone());
606
607 final ConditionVariable requestDestroyed = new ConditionVariable(false);
608 stream.setOnDestroyedCallbackForTests(new Runnable() {
609 @Override
610 public void run() {
611 requestDestroyed.open();
612 }
613 });
614
615 // Shutdown the executor, so posting the task will throw an exception.
616 callback.shutdownExecutor();
617 ByteBuffer readBuffer = ByteBuffer.allocateDirect(5);
618 stream.read(readBuffer);
619 // Callback will never be called again because executor is shutdown,
620 // but stream will be destroyed from network thread.
621 requestDestroyed.block();
622
623 assertFalse(callback.isDone());
624 assertTrue(stream.isDone());
625 }
626
627 /**
628 * Callback that shutdowns the engine when the stream has succeeded
629 * or failed.
630 */
631 class ShutdownTestBidirectionalStreamCallback extends TestBidirectionalStrea mCallback {
632 @Override
633 public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info ) {
634 mTestFramework.mCronetEngine.shutdown();
635 // Clear mCronetEngine so it doesn't get shutdown second time in tea rDown().
636 mTestFramework.mCronetEngine = null;
637 super.onSucceeded(stream, info);
638 }
639
640 @Override
641 public void onFailed(
642 BidirectionalStream stream, UrlResponseInfo info, CronetExceptio n error) {
643 mTestFramework.mCronetEngine.shutdown();
644 // Clear mCronetEngine so it doesn't get shutdown second time in tea rDown().
645 mTestFramework.mCronetEngine = null;
646 super.onFailed(stream, info, error);
647 }
648 }
649
650 @SmallTest
651 @Feature({"Cronet"})
652 public void testShutdown() throws Exception {
653 TestBidirectionalStreamCallback callback = new ShutdownTestBidirectional StreamCallback();
654 // Block callback when response starts to verify that shutdown fails
655 // if there are active stream.
656 callback.setAutoAdvance(false);
657 BidirectionalStream.Builder builder =
658 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
659 callback.getExecutor(), mTestFramework.mCronetEngine);
660 CronetBidirectionalStream stream =
661 (CronetBidirectionalStream) builder.setHttpMethod("GET").build() ;
662 stream.start();
663 try {
664 mTestFramework.mCronetEngine.shutdown();
665 fail("Should throw an exception");
666 } catch (Exception e) {
667 assertEquals("Cannot shutdown with active requests.", e.getMessage() );
668 }
669
670 callback.waitForNextReadStep();
671 assertEquals(ResponseStep.ON_RESPONSE_STARTED, callback.mResponseStep);
672 try {
673 mTestFramework.mCronetEngine.shutdown();
674 fail("Should throw an exception");
675 } catch (Exception e) {
676 assertEquals("Cannot shutdown with active requests.", e.getMessage() );
677 }
678 callback.startNextRead(stream);
679
680 callback.waitForNextReadStep();
681 assertEquals(ResponseStep.ON_READ_COMPLETED, callback.mResponseStep);
682 try {
683 mTestFramework.mCronetEngine.shutdown();
684 fail("Should throw an exception");
685 } catch (Exception e) {
686 assertEquals("Cannot shutdown with active requests.", e.getMessage() );
687 }
688
689 // May not have read all the data, in theory. Just enable auto-advance
690 // and finish the request.
691 callback.setAutoAdvance(true);
692 callback.startNextRead(stream);
693 callback.blockForDone();
694 }
695
696 @SmallTest
697 @Feature({"Cronet"})
698 public void testShutdownAfterError() throws Exception {
699 TestBidirectionalStreamCallback callback = new ShutdownTestBidirectional StreamCallback();
700 BidirectionalStream.Builder builder =
701 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
702 callback.getExecutor(), mTestFramework.mCronetEngine);
703 CronetBidirectionalStream stream =
704 (CronetBidirectionalStream) builder.setHttpMethod("GET").build() ;
705 stream.start();
706 callback.setFailure(FailureType.THROW_SYNC, ResponseStep.ON_READ_COMPLET ED);
707 callback.blockForDone();
708 assertTrue(callback.mOnErrorCalled);
709 }
710
711 @SmallTest
712 @Feature({"Cronet"})
713 public void testShutdownAfterCancel() throws Exception {
714 TestBidirectionalStreamCallback callback = new ShutdownTestBidirectional StreamCallback();
715 BidirectionalStream.Builder builder =
716 new BidirectionalStream.Builder(Http2TestServer.getEchoMethodUrl (), callback,
717 callback.getExecutor(), mTestFramework.mCronetEngine);
718 CronetBidirectionalStream stream =
719 (CronetBidirectionalStream) builder.setHttpMethod("GET").build() ;
720
721 // Block callback when response starts to verify that shutdown fails
722 // if there are active requests.
723 callback.setAutoAdvance(false);
724 stream.start();
725 try {
726 mTestFramework.mCronetEngine.shutdown();
727 fail("Should throw an exception");
728 } catch (Exception e) {
729 assertEquals("Cannot shutdown with active requests.", e.getMessage() );
730 }
731 callback.waitForNextReadStep();
732 assertEquals(ResponseStep.ON_RESPONSE_STARTED, callback.mResponseStep);
733 stream.cancel();
734 }
735
736 // Returns the contents of byteBuffer, from its position() to its limit(),
737 // as a String. Does not modify byteBuffer's position().
738 private String bufferContentsToString(ByteBuffer byteBuffer, int start, int end) {
739 // Use a duplicate to avoid modifying byteBuffer.
740 ByteBuffer duplicate = byteBuffer.duplicate();
741 duplicate.position(start);
742 duplicate.limit(end);
743 byte[] contents = new byte[duplicate.remaining()];
744 duplicate.get(contents);
745 return new String(contents);
746 }
121 } 747 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698