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

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

Powered by Google App Engine
This is Rietveld 408576698