1 // Copyright 2019 The Chromium Authors 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.test; 6 7 import static com.google.common.truth.Truth.assertThat; 8 import static com.google.common.truth.Truth.assertWithMessage; 9 10 import static org.junit.Assert.assertThrows; 11 12 import static org.chromium.net.truth.UrlResponseInfoSubject.assertThat; 13 14 import android.os.ConditionVariable; 15 16 import androidx.test.core.app.ApplicationProvider; 17 import androidx.test.ext.junit.runners.AndroidJUnit4; 18 import androidx.test.filters.SmallTest; 19 20 import com.google.common.collect.Maps; 21 22 import org.junit.After; 23 import org.junit.Before; 24 import org.junit.Test; 25 import org.junit.runner.RunWith; 26 27 import org.chromium.net.CronetEngine; 28 import org.chromium.net.CronetException; 29 import org.chromium.net.InlineExecutionProhibitedException; 30 import org.chromium.net.TestUploadDataProvider; 31 import org.chromium.net.TestUrlRequestCallback; 32 import org.chromium.net.TestUrlRequestCallback.ResponseStep; 33 import org.chromium.net.UploadDataProvider; 34 import org.chromium.net.UploadDataSink; 35 import org.chromium.net.UrlRequest; 36 import org.chromium.net.UrlRequest.Status; 37 import org.chromium.net.UrlRequest.StatusListener; 38 import org.chromium.net.UrlResponseInfo; 39 import org.chromium.net.apihelpers.UploadDataProviders; 40 41 import java.io.IOException; 42 import java.net.URI; 43 import java.nio.ByteBuffer; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.Objects; 49 import java.util.concurrent.Executor; 50 import java.util.concurrent.Executors; 51 import java.util.concurrent.atomic.AtomicBoolean; 52 53 /** Test functionality of FakeUrlRequest. */ 54 @RunWith(AndroidJUnit4.class) 55 public class FakeUrlRequestTest { 56 private CronetEngine mFakeCronetEngine; 57 private FakeCronetController mFakeCronetController; 58 checkStatus(FakeUrlRequest request, final int expectedStatus)59 private static void checkStatus(FakeUrlRequest request, final int expectedStatus) { 60 ConditionVariable foundStatus = new ConditionVariable(); 61 request.getStatus( 62 new StatusListener() { 63 @Override 64 public void onStatus(int status) { 65 assertThat(status).isEqualTo(expectedStatus); 66 foundStatus.open(); 67 } 68 }); 69 foundStatus.block(); 70 } 71 72 // Asserts that read happens a specified number of times assertReadCalled( int numberOfTimes, TestUrlRequestCallback callback, UrlRequest request)73 private static void assertReadCalled( 74 int numberOfTimes, TestUrlRequestCallback callback, UrlRequest request) { 75 for (int i = 1; i <= numberOfTimes; i++) { 76 callback.startNextRead(request); 77 callback.waitForNextStep(); 78 assertWithMessage( 79 "Expected read to happen " 80 + numberOfTimes 81 + " times but got " 82 + i 83 + " times.") 84 .that(callback.mResponseStep) 85 .isEqualTo(ResponseStep.ON_READ_COMPLETED); 86 } 87 } 88 89 private static class EchoBodyResponseMatcher implements ResponseMatcher { 90 private final String mUrl; 91 EchoBodyResponseMatcher(String url)92 EchoBodyResponseMatcher(String url) { 93 mUrl = url; 94 } 95 EchoBodyResponseMatcher()96 EchoBodyResponseMatcher() { 97 this(null); 98 } 99 100 @Override getMatchingResponse( String url, String httpMethod, List<Map.Entry<String, String>> headers, byte[] body)101 public FakeUrlResponse getMatchingResponse( 102 String url, 103 String httpMethod, 104 List<Map.Entry<String, String>> headers, 105 byte[] body) { 106 if (mUrl == null || mUrl.equals(url)) { 107 return new FakeUrlResponse.Builder().setResponseBody(body).build(); 108 } 109 return null; 110 } 111 } 112 113 @Before setUp()114 public void setUp() { 115 mFakeCronetController = new FakeCronetController(); 116 mFakeCronetEngine = 117 mFakeCronetController 118 .newFakeCronetEngineBuilder(ApplicationProvider.getApplicationContext()) 119 .build(); 120 } 121 122 @After tearDown()123 public void tearDown() { 124 mFakeCronetEngine.shutdown(); 125 } 126 127 @Test 128 @SmallTest testDefaultResponse()129 public void testDefaultResponse() { 130 // Setup the basic response. 131 String responseText = "response text"; 132 FakeUrlResponse response = 133 new FakeUrlResponse.Builder().setResponseBody(responseText.getBytes()).build(); 134 String url = "www.response.com"; 135 mFakeCronetController.addResponseForUrl(response, url); 136 137 // Run the request. 138 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 139 callback.setAutoAdvance(false); 140 FakeUrlRequest request = 141 (FakeUrlRequest) 142 mFakeCronetEngine 143 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 144 .build(); 145 request.start(); 146 callback.waitForNextStep(); 147 148 // Verify correct callback methods called and correct response returned. 149 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 150 callback.startNextRead(request); 151 callback.waitForNextStep(); 152 153 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_READ_COMPLETED); 154 callback.startNextRead(request); 155 callback.waitForNextStep(); 156 157 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 158 callback.blockForDone(); 159 160 assertThat(responseText).isEqualTo(callback.mResponseAsString); 161 } 162 163 @Test 164 @SmallTest testBuilderChecks()165 public void testBuilderChecks() { 166 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 167 NullPointerException e = 168 assertThrows( 169 NullPointerException.class, 170 () -> 171 mFakeCronetEngine.newUrlRequestBuilder( 172 null, callback, callback.getExecutor())); 173 assertThat(e).hasMessageThat().isEqualTo("URL is required."); 174 175 e = 176 assertThrows( 177 NullPointerException.class, 178 () -> 179 mFakeCronetEngine.newUrlRequestBuilder( 180 "url", null, callback.getExecutor())); 181 assertThat(e).hasMessageThat().isEqualTo("Callback is required."); 182 183 e = 184 assertThrows( 185 NullPointerException.class, 186 () -> mFakeCronetEngine.newUrlRequestBuilder("url", callback, null)); 187 assertThat(e).hasMessageThat().isEqualTo("Executor is required."); 188 // Verify successful creation doesn't throw. 189 mFakeCronetEngine.newUrlRequestBuilder("url", callback, callback.getExecutor()); 190 } 191 192 @Test 193 @SmallTest testSetHttpMethodWhenNullFails()194 public void testSetHttpMethodWhenNullFails() { 195 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 196 FakeUrlRequest request = 197 (FakeUrlRequest) 198 mFakeCronetEngine 199 .newUrlRequestBuilder("url", callback, callback.getExecutor()) 200 .build(); 201 // Check exception thrown for null method. 202 NullPointerException e = 203 assertThrows(NullPointerException.class, () -> request.setHttpMethod(null)); 204 assertThat(e).hasMessageThat().isEqualTo("Method is required."); 205 } 206 207 @Test 208 @SmallTest testSetHttpMethodWhenInvalidFails()209 public void testSetHttpMethodWhenInvalidFails() { 210 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 211 FakeUrlRequest request = 212 (FakeUrlRequest) 213 mFakeCronetEngine 214 .newUrlRequestBuilder("url", callback, callback.getExecutor()) 215 .build(); 216 217 // Check exception thrown for invalid method. 218 String method = "BADMETHOD"; 219 IllegalArgumentException e = 220 assertThrows(IllegalArgumentException.class, () -> request.setHttpMethod(method)); 221 assertThat(e).hasMessageThat().isEqualTo("Invalid http method: " + method); 222 } 223 224 @Test 225 @SmallTest testSetHttpMethodSetsMethodToCorrectMethod()226 public void testSetHttpMethodSetsMethodToCorrectMethod() { 227 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 228 FakeUrlRequest request = 229 (FakeUrlRequest) 230 mFakeCronetEngine 231 .newUrlRequestBuilder("url", callback, callback.getExecutor()) 232 .build(); 233 String testMethod = "PUT"; 234 // Use an atomic because it is set in an inner class. We do not actually need atomic for a 235 // multi-threaded operation here. 236 AtomicBoolean foundMethod = new AtomicBoolean(); 237 238 mFakeCronetController.addResponseMatcher( 239 new ResponseMatcher() { 240 @Override 241 public FakeUrlResponse getMatchingResponse( 242 String url, 243 String httpMethod, 244 List<Map.Entry<String, String>> headers, 245 byte[] body) { 246 assertThat(httpMethod).isEqualTo(testMethod); 247 foundMethod.set(true); 248 // It doesn't matter if a response is actually returned. 249 return null; 250 } 251 }); 252 253 // Check no exception for correct method. 254 request.setHttpMethod(testMethod); 255 256 // Run the request so that the ResponseMatcher we set is checked. 257 request.start(); 258 callback.blockForDone(); 259 260 assertThat(foundMethod.get()).isTrue(); 261 } 262 263 @Test 264 @SmallTest testAddHeader()265 public void testAddHeader() { 266 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 267 FakeUrlRequest request = 268 (FakeUrlRequest) 269 mFakeCronetEngine 270 .newUrlRequestBuilder("TEST_URL", callback, callback.getExecutor()) 271 .build(); 272 String headerKey = "HEADERNAME"; 273 String headerValue = "HEADERVALUE"; 274 request.addHeader(headerKey, headerValue); 275 // Use an atomic because it is set in an inner class. We do not actually need atomic for a 276 // multi-threaded operation here. 277 AtomicBoolean foundEntry = new AtomicBoolean(); 278 mFakeCronetController.addResponseMatcher( 279 new ResponseMatcher() { 280 @Override 281 public FakeUrlResponse getMatchingResponse( 282 String url, 283 String httpMethod, 284 List<Map.Entry<String, String>> headers, 285 byte[] body) { 286 assertThat(headers) 287 .containsExactly(Maps.immutableEntry(headerKey, headerValue)); 288 foundEntry.set(true); 289 // It doesn't matter if a response is actually returned. 290 return null; 291 } 292 }); 293 // Run the request so that the ResponseMatcher we set is checked. 294 request.start(); 295 callback.blockForDone(); 296 297 assertThat(foundEntry.get()).isTrue(); 298 } 299 300 @Test 301 @SmallTest testRequestDoesNotStartWhenEngineShutDown()302 public void testRequestDoesNotStartWhenEngineShutDown() { 303 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 304 FakeUrlRequest request = 305 (FakeUrlRequest) 306 mFakeCronetEngine 307 .newUrlRequestBuilder("TEST_URL", callback, callback.getExecutor()) 308 .build(); 309 310 mFakeCronetEngine.shutdown(); 311 IllegalStateException e = assertThrows(IllegalStateException.class, request::start); 312 assertThat(e) 313 .hasMessageThat() 314 .isEqualTo("This request's CronetEngine is already shutdown."); 315 } 316 317 @Test 318 @SmallTest testRequestStopsWhenCanceled()319 public void testRequestStopsWhenCanceled() { 320 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 321 FakeUrlRequest request = 322 (FakeUrlRequest) 323 mFakeCronetEngine 324 .newUrlRequestBuilder("TEST_URL", callback, callback.getExecutor()) 325 .build(); 326 callback.setAutoAdvance(false); 327 request.start(); 328 callback.waitForNextStep(); 329 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 330 331 request.cancel(); 332 callback.waitForNextStep(); 333 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_CANCELED); 334 assertThat(callback.mResponseAsString).isEmpty(); 335 } 336 337 @Test 338 @SmallTest testRecievedByteCountInUrlResponseInfoIsEqualToResponseLength()339 public void testRecievedByteCountInUrlResponseInfoIsEqualToResponseLength() { 340 // Setup the basic response. 341 String responseText = "response text"; 342 FakeUrlResponse response = 343 new FakeUrlResponse.Builder().setResponseBody(responseText.getBytes()).build(); 344 String url = "TEST_URL"; 345 mFakeCronetController.addResponseForUrl(response, url); 346 347 // Run the request. 348 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 349 FakeUrlRequest request = 350 (FakeUrlRequest) 351 mFakeCronetEngine 352 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 353 .build(); 354 request.start(); 355 callback.blockForDone(); 356 357 assertThat(callback.getResponseInfoWithChecks()) 358 .hasReceivedByteCountThat() 359 .isEqualTo(responseText.length()); 360 } 361 362 @Test 363 @SmallTest testRedirectResponse()364 public void testRedirectResponse() { 365 // Setup the basic response. 366 String responseText = "response text"; 367 String redirectLocation = "/redirect_location"; 368 FakeUrlResponse response = 369 new FakeUrlResponse.Builder() 370 .setResponseBody(responseText.getBytes()) 371 .addHeader("location", redirectLocation) 372 .setHttpStatusCode(300) 373 .build(); 374 375 String url = "TEST_URL"; 376 mFakeCronetController.addResponseForUrl(response, url); 377 378 String redirectText = "redirect text"; 379 FakeUrlResponse redirectToResponse = 380 new FakeUrlResponse.Builder().setResponseBody(redirectText.getBytes()).build(); 381 String redirectUrl = URI.create(url).resolve(redirectLocation).toString(); 382 383 mFakeCronetController.addResponseForUrl(redirectToResponse, redirectUrl); 384 385 // Run the request. 386 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 387 FakeUrlRequest request = 388 (FakeUrlRequest) 389 mFakeCronetEngine 390 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 391 .build(); 392 request.start(); 393 callback.blockForDone(); 394 395 // Verify response from redirected URL is returned. 396 assertThat(callback.mResponseAsString).isEqualTo(redirectText); 397 } 398 399 @Test 400 @SmallTest testRedirectResponseWithNoHeaderFails()401 public void testRedirectResponseWithNoHeaderFails() { 402 // Setup the basic response. 403 String responseText = "response text"; 404 FakeUrlResponse response = 405 new FakeUrlResponse.Builder() 406 .setResponseBody(responseText.getBytes()) 407 .setHttpStatusCode(300) 408 .build(); 409 410 String url = "TEST_URL"; 411 mFakeCronetController.addResponseForUrl(response, url); 412 413 // Run the request. 414 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 415 FakeUrlRequest request = 416 (FakeUrlRequest) 417 mFakeCronetEngine 418 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 419 .build(); 420 request.start(); 421 callback.blockForDone(); 422 423 // Verify response from redirected URL is returned. 424 assertThat(callback.mResponseStep).isEqualTo(TestUrlRequestCallback.ResponseStep.ON_FAILED); 425 } 426 427 @Test 428 @SmallTest testResponseLongerThanBuffer()429 public void testResponseLongerThanBuffer() { 430 // Build a long response string that is 3x the buffer size. 431 final int bufferStringLengthMultiplier = 3; 432 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 433 callback.setAutoAdvance(false); 434 String longResponseString = 435 new String(new char[callback.mReadBufferSize * bufferStringLengthMultiplier]); 436 437 String longResponseUrl = "https://www.longResponseUrl.com"; 438 439 FakeUrlResponse reallyLongResponse = 440 new FakeUrlResponse.Builder() 441 .setResponseBody(longResponseString.getBytes()) 442 .build(); 443 mFakeCronetController.addResponseForUrl(reallyLongResponse, longResponseUrl); 444 445 FakeUrlRequest request = 446 (FakeUrlRequest) 447 mFakeCronetEngine 448 .newUrlRequestBuilder( 449 longResponseUrl, callback, callback.getExecutor()) 450 .build(); 451 request.start(); 452 callback.waitForNextStep(); 453 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 454 455 // Asserts that read happens bufferStringLengthMultiplier times 456 assertReadCalled(bufferStringLengthMultiplier, callback, request); 457 458 callback.startNextRead(request); 459 callback.waitForNextStep(); 460 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 461 assertThat(Objects.equals(callback.mResponseAsString, longResponseString)).isTrue(); 462 } 463 464 @Test 465 @SmallTest testStatusInvalidBeforeStart()466 public void testStatusInvalidBeforeStart() { 467 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 468 FakeUrlRequest request = 469 (FakeUrlRequest) 470 mFakeCronetEngine 471 .newUrlRequestBuilder("URL", callback, callback.getExecutor()) 472 .build(); 473 474 checkStatus(request, Status.INVALID); 475 request.start(); 476 callback.blockForDone(); 477 } 478 479 @Test 480 @SmallTest testStatusIdleWhenWaitingForRead()481 public void testStatusIdleWhenWaitingForRead() { 482 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 483 callback.setAutoAdvance(false); 484 FakeUrlRequest request = 485 (FakeUrlRequest) 486 mFakeCronetEngine 487 .newUrlRequestBuilder("URL", callback, callback.getExecutor()) 488 .build(); 489 request.start(); 490 checkStatus(request, Status.IDLE); 491 callback.setAutoAdvance(true); 492 callback.startNextRead(request); 493 callback.blockForDone(); 494 } 495 496 @Test 497 @SmallTest testStatusIdleWhenWaitingForRedirect()498 public void testStatusIdleWhenWaitingForRedirect() { 499 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 500 callback.setAutoAdvance(false); 501 String initialURL = "initialURL"; 502 String secondURL = "secondURL"; 503 mFakeCronetController.addRedirectResponse(secondURL, initialURL); 504 FakeUrlRequest request = 505 (FakeUrlRequest) 506 mFakeCronetEngine 507 .newUrlRequestBuilder(initialURL, callback, callback.getExecutor()) 508 .build(); 509 510 request.start(); 511 callback.waitForNextStep(); 512 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RECEIVED_REDIRECT); 513 checkStatus(request, Status.IDLE); 514 callback.setAutoAdvance(true); 515 request.followRedirect(); 516 callback.blockForDone(); 517 } 518 519 @Test 520 @SmallTest testStatusInvalidWhenDone()521 public void testStatusInvalidWhenDone() { 522 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 523 FakeUrlRequest request = 524 (FakeUrlRequest) 525 mFakeCronetEngine 526 .newUrlRequestBuilder("URL", callback, callback.getExecutor()) 527 .build(); 528 request.start(); 529 callback.blockForDone(); 530 checkStatus(request, Status.INVALID); 531 } 532 533 @Test 534 @SmallTest testIsDoneWhenComplete()535 public void testIsDoneWhenComplete() { 536 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 537 FakeUrlRequest request = 538 (FakeUrlRequest) 539 mFakeCronetEngine 540 .newUrlRequestBuilder("", callback, callback.getExecutor()) 541 .build(); 542 543 request.start(); 544 callback.blockForDone(); 545 546 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 547 assertThat(request.isDone()).isTrue(); 548 } 549 550 @Test 551 @SmallTest testSetUploadDataProviderAfterStart()552 public void testSetUploadDataProviderAfterStart() { 553 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 554 FakeUrlRequest request = 555 (FakeUrlRequest) 556 mFakeCronetEngine 557 .newUrlRequestBuilder("", callback, callback.getExecutor()) 558 .addHeader("Content-Type", "useless/string") 559 .build(); 560 String body = "body"; 561 request.setUploadDataProvider( 562 UploadDataProviders.create(body.getBytes()), callback.getExecutor()); 563 request.start(); 564 // Must wait for the request to prevent a race in the State since it is reported in the 565 // error. 566 callback.blockForDone(); 567 568 IllegalStateException e = 569 assertThrows( 570 IllegalStateException.class, 571 () -> 572 request.setUploadDataProvider( 573 UploadDataProviders.create(body.getBytes()), 574 callback.getExecutor())); 575 assertThat(e).hasMessageThat().isEqualTo("Request is already started. State is: 7"); 576 } 577 578 @Test 579 @SmallTest testUrlChainIsCorrectForSuccessRequest()580 public void testUrlChainIsCorrectForSuccessRequest() { 581 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 582 String testUrl = "TEST_URL"; 583 List<String> expectedUrlChain = new ArrayList<>(); 584 expectedUrlChain.add(testUrl); 585 FakeUrlRequest request = 586 (FakeUrlRequest) 587 mFakeCronetEngine 588 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 589 .build(); 590 request.start(); 591 callback.blockForDone(); 592 593 assertThat(callback.getResponseInfoWithChecks()) 594 .hasUrlChainThat() 595 .isEqualTo(expectedUrlChain); 596 } 597 598 @Test 599 @SmallTest testUrlChainIsCorrectForRedirectRequest()600 public void testUrlChainIsCorrectForRedirectRequest() { 601 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 602 String testUrl1 = "TEST_URL1"; 603 String testUrl2 = "TEST_URL2"; 604 mFakeCronetController.addRedirectResponse(testUrl2, testUrl1); 605 List<String> expectedUrlChain = new ArrayList<>(); 606 expectedUrlChain.add(testUrl1); 607 expectedUrlChain.add(testUrl2); 608 FakeUrlRequest request = 609 (FakeUrlRequest) 610 mFakeCronetEngine 611 .newUrlRequestBuilder(testUrl1, callback, callback.getExecutor()) 612 .build(); 613 request.start(); 614 callback.blockForDone(); 615 616 assertThat(callback.getResponseInfoWithChecks()) 617 .hasUrlChainThat() 618 .isEqualTo(expectedUrlChain); 619 } 620 621 @Test 622 @SmallTest testResponseCodeCorrect()623 public void testResponseCodeCorrect() { 624 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 625 String testUrl = "TEST_URL"; 626 int expectedResponseCode = 208; 627 mFakeCronetController.addResponseForUrl( 628 new FakeUrlResponse.Builder().setHttpStatusCode(expectedResponseCode).build(), 629 testUrl); 630 FakeUrlRequest request = 631 (FakeUrlRequest) 632 mFakeCronetEngine 633 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 634 .build(); 635 request.start(); 636 callback.blockForDone(); 637 638 assertThat(callback.getResponseInfoWithChecks()) 639 .hasHttpStatusCodeThat() 640 .isEqualTo(expectedResponseCode); 641 } 642 643 @Test 644 @SmallTest testResponseTextCorrect()645 public void testResponseTextCorrect() { 646 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 647 String testUrl = "TEST_URL"; 648 int expectedResponseCode = 208; 649 String expectedResponseText = "Already Reported"; 650 mFakeCronetController.addResponseForUrl( 651 new FakeUrlResponse.Builder().setHttpStatusCode(expectedResponseCode).build(), 652 testUrl); 653 FakeUrlRequest request = 654 (FakeUrlRequest) 655 mFakeCronetEngine 656 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 657 .build(); 658 request.start(); 659 callback.blockForDone(); 660 661 assertThat(callback.getResponseInfoWithChecks()) 662 .hasHttpStatusTextThat() 663 .isEqualTo(expectedResponseText); 664 } 665 666 @Test 667 @SmallTest testResponseWasCachedCorrect()668 public void testResponseWasCachedCorrect() { 669 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 670 String testUrl = "TEST_URL"; 671 mFakeCronetController.addResponseForUrl( 672 new FakeUrlResponse.Builder().setWasCached(true).build(), testUrl); 673 FakeUrlRequest request = 674 (FakeUrlRequest) 675 mFakeCronetEngine 676 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 677 .build(); 678 request.start(); 679 callback.blockForDone(); 680 681 assertThat(callback.getResponseInfoWithChecks()).wasCached(); 682 } 683 684 @Test 685 @SmallTest testResponseNegotiatedProtocolCorrect()686 public void testResponseNegotiatedProtocolCorrect() { 687 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 688 String testUrl = "TEST_URL"; 689 String expectedNegotiatedProtocol = "TEST_NEGOTIATED_PROTOCOL"; 690 mFakeCronetController.addResponseForUrl( 691 new FakeUrlResponse.Builder() 692 .setNegotiatedProtocol(expectedNegotiatedProtocol) 693 .build(), 694 testUrl); 695 FakeUrlRequest request = 696 (FakeUrlRequest) 697 mFakeCronetEngine 698 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 699 .build(); 700 request.start(); 701 callback.blockForDone(); 702 703 assertThat(callback.getResponseInfoWithChecks()) 704 .hasNegotiatedProtocolThat() 705 .isEqualTo(expectedNegotiatedProtocol); 706 } 707 708 @Test 709 @SmallTest testResponseProxyServerCorrect()710 public void testResponseProxyServerCorrect() { 711 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 712 String testUrl = "TEST_URL"; 713 String expectedProxyServer = "TEST_PROXY_SERVER"; 714 mFakeCronetController.addResponseForUrl( 715 new FakeUrlResponse.Builder().setProxyServer(expectedProxyServer).build(), testUrl); 716 FakeUrlRequest request = 717 (FakeUrlRequest) 718 mFakeCronetEngine 719 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 720 .build(); 721 request.start(); 722 callback.blockForDone(); 723 724 assertThat(callback.getResponseInfoWithChecks()) 725 .hasProxyServerThat() 726 .isEqualTo(expectedProxyServer); 727 } 728 729 @Test 730 @SmallTest testDirectExecutorDisabledByDefault()731 public void testDirectExecutorDisabledByDefault() { 732 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 733 callback.setAllowDirectExecutor(true); 734 Executor myExecutor = 735 new Executor() { 736 @Override 737 public void execute(Runnable command) { 738 command.run(); 739 } 740 }; 741 FakeUrlRequest request = 742 (FakeUrlRequest) 743 mFakeCronetEngine.newUrlRequestBuilder("url", callback, myExecutor).build(); 744 745 request.start(); 746 callback.blockForDone(); 747 748 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_FAILED); 749 // Checks that the exception from {@link DirectPreventingExecutor} was successfully returned 750 // to the callback in the onFailed method. 751 assertThat(callback.mError) 752 .hasCauseThat() 753 .isInstanceOf(InlineExecutionProhibitedException.class); 754 } 755 756 @Test 757 @SmallTest testLotsOfCallsToReadDoesntOverflow()758 public void testLotsOfCallsToReadDoesntOverflow() { 759 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 760 callback.setAutoAdvance(false); 761 // Make the buffer size small so there are lots of calls to read(). 762 callback.mReadBufferSize = 1; 763 String testUrl = "TEST_URL"; 764 int responseLength = 1024; 765 byte[] byteArray = new byte[responseLength]; 766 Arrays.fill(byteArray, (byte) 1); 767 String longResponseString = new String(byteArray); 768 mFakeCronetController.addResponseForUrl( 769 new FakeUrlResponse.Builder() 770 .setResponseBody(longResponseString.getBytes()) 771 .build(), 772 testUrl); 773 FakeUrlRequest request = 774 (FakeUrlRequest) 775 mFakeCronetEngine 776 .newUrlRequestBuilder(testUrl, callback, callback.getExecutor()) 777 .allowDirectExecutor() 778 .build(); 779 request.start(); 780 callback.waitForNextStep(); 781 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 782 783 // Asserts that read happens responseLength times 784 assertReadCalled(responseLength, callback, request); 785 786 callback.startNextRead(request); 787 callback.waitForNextStep(); 788 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 789 assertThat(callback.mResponseAsString).isEqualTo(longResponseString); 790 } 791 792 @Test 793 @SmallTest testLotsOfCallsToReadDoesntOverflowWithDirectExecutor()794 public void testLotsOfCallsToReadDoesntOverflowWithDirectExecutor() { 795 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 796 callback.setAutoAdvance(false); 797 callback.setAllowDirectExecutor(true); 798 // Make the buffer size small so there are lots of calls to read(). 799 callback.mReadBufferSize = 1; 800 String testUrl = "TEST_URL"; 801 int responseLength = 1024; 802 byte[] byteArray = new byte[responseLength]; 803 Arrays.fill(byteArray, (byte) 1); 804 String longResponseString = new String(byteArray); 805 Executor myExecutor = 806 new Executor() { 807 @Override 808 public void execute(Runnable command) { 809 command.run(); 810 } 811 }; 812 mFakeCronetController.addResponseForUrl( 813 new FakeUrlResponse.Builder() 814 .setResponseBody(longResponseString.getBytes()) 815 .build(), 816 testUrl); 817 FakeUrlRequest request = 818 (FakeUrlRequest) 819 mFakeCronetEngine 820 .newUrlRequestBuilder(testUrl, callback, myExecutor) 821 .allowDirectExecutor() 822 .build(); 823 request.start(); 824 callback.waitForNextStep(); 825 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 826 827 // Asserts that read happens buffer length x multiplier times 828 assertReadCalled(responseLength, callback, request); 829 830 callback.startNextRead(request); 831 callback.waitForNextStep(); 832 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 833 assertThat(callback.mResponseAsString).isEqualTo(longResponseString); 834 } 835 836 @Test 837 @SmallTest testDoubleReadFails()838 public void testDoubleReadFails() throws Exception { 839 UrlRequest.Callback callback = new StubCallback(); 840 FakeUrlRequest request = 841 (FakeUrlRequest) 842 mFakeCronetEngine 843 .newUrlRequestBuilder( 844 "url", callback, Executors.newSingleThreadExecutor()) 845 .build(); 846 ByteBuffer buffer = ByteBuffer.allocateDirect(32 * 1024); 847 848 request.start(); 849 request.read(buffer); 850 851 IllegalStateException e = 852 assertThrows(IllegalStateException.class, () -> request.read(buffer)); 853 assertThat(e).hasMessageThat().isEqualTo("Invalid state transition - expected 4 but was 7"); 854 } 855 856 @Test 857 @SmallTest testReadWhileRedirectingFails()858 public void testReadWhileRedirectingFails() { 859 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 860 callback.setAutoAdvance(false); 861 String url = "url"; 862 FakeUrlRequest request = 863 (FakeUrlRequest) 864 mFakeCronetEngine 865 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 866 .build(); 867 mFakeCronetController.addRedirectResponse("location", url); 868 request.start(); 869 IllegalStateException e = 870 assertThrows(IllegalStateException.class, () -> callback.startNextRead(request)); 871 assertThat(e).hasMessageThat().isEqualTo("Invalid state transition - expected 4 but was 3"); 872 callback.waitForNextStep(); 873 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RECEIVED_REDIRECT); 874 callback.setAutoAdvance(true); 875 request.followRedirect(); 876 callback.blockForDone(); 877 } 878 879 @Test 880 @SmallTest testShuttingDownCronetEngineWithActiveRequestFails()881 public void testShuttingDownCronetEngineWithActiveRequestFails() { 882 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 883 callback.setAutoAdvance(false); 884 String url = "url"; 885 FakeUrlRequest request = 886 (FakeUrlRequest) 887 mFakeCronetEngine 888 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 889 .build(); 890 request.start(); 891 IllegalStateException e = 892 assertThrows(IllegalStateException.class, mFakeCronetEngine::shutdown); 893 assertThat(e).hasMessageThat().isEqualTo("Cannot shutdown with running requests."); 894 callback.waitForNextStep(); 895 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_RESPONSE_STARTED); 896 callback.setAutoAdvance(true); 897 callback.startNextRead(request); 898 callback.blockForDone(); 899 mFakeCronetEngine.shutdown(); 900 } 901 902 @Test 903 @SmallTest testDefaultResponseIs404()904 public void testDefaultResponseIs404() { 905 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 906 String url = "url"; 907 FakeUrlRequest request = 908 (FakeUrlRequest) 909 mFakeCronetEngine 910 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 911 .build(); 912 913 request.start(); 914 callback.blockForDone(); 915 916 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(404); 917 } 918 919 @Test 920 @SmallTest testUploadSetDataProviderChecksForNullUploadDataProvider()921 public void testUploadSetDataProviderChecksForNullUploadDataProvider() throws Exception { 922 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 923 String url = "url"; 924 FakeUrlRequest.Builder builder = 925 (FakeUrlRequest.Builder) 926 mFakeCronetEngine.newUrlRequestBuilder( 927 url, callback, callback.getExecutor()); 928 929 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 930 931 NullPointerException e = 932 assertThrows( 933 NullPointerException.class, 934 () -> builder.setUploadDataProvider(null, callback.getExecutor())); 935 assertThat(e).hasMessageThat().isEqualTo("Invalid UploadDataProvider."); 936 } 937 938 @Test 939 @SmallTest testUploadSetDataProviderChecksForContentTypeHeader()940 public void testUploadSetDataProviderChecksForContentTypeHeader() throws Exception { 941 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 942 String url = "url"; 943 FakeUrlRequest.Builder builder = 944 (FakeUrlRequest.Builder) 945 mFakeCronetEngine.newUrlRequestBuilder( 946 url, callback, callback.getExecutor()); 947 948 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 949 950 TestUploadDataProvider dataProvider = 951 new TestUploadDataProvider( 952 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 953 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 954 IllegalArgumentException e = 955 assertThrows(IllegalArgumentException.class, () -> builder.build().start()); 956 assertThat(e) 957 .hasMessageThat() 958 .isEqualTo("Requests with upload data must have a Content-Type."); 959 } 960 961 @Test 962 @SmallTest testUploadWithEmptyBody()963 public void testUploadWithEmptyBody() throws Exception { 964 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 965 String url = "url"; 966 FakeUrlRequest.Builder builder = 967 (FakeUrlRequest.Builder) 968 mFakeCronetEngine.newUrlRequestBuilder( 969 url, callback, callback.getExecutor()); 970 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 971 TestUploadDataProvider dataProvider = 972 new TestUploadDataProvider( 973 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 974 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 975 builder.addHeader("Content-Type", "useless/string"); 976 builder.build().start(); 977 callback.blockForDone(); 978 979 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 980 assertThat(callback.mResponseAsString).isEmpty(); 981 dataProvider.assertClosed(); 982 } 983 984 @Test 985 @SmallTest testUploadSync()986 public void testUploadSync() throws Exception { 987 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 988 String url = "url"; 989 String body = "test"; 990 FakeUrlRequest.Builder builder = 991 (FakeUrlRequest.Builder) 992 mFakeCronetEngine.newUrlRequestBuilder( 993 url, callback, callback.getExecutor()); 994 TestUploadDataProvider dataProvider = 995 new TestUploadDataProvider( 996 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 997 998 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 999 dataProvider.addRead(body.getBytes()); 1000 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1001 builder.addHeader("Content-Type", "useless/string"); 1002 builder.build().start(); 1003 callback.blockForDone(); 1004 dataProvider.assertClosed(); 1005 1006 assertThat(dataProvider.getUploadedLength()).isEqualTo(4); 1007 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1008 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1009 1010 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1011 assertThat(callback.mResponseAsString).isEqualTo("test"); 1012 } 1013 1014 @Test 1015 @SmallTest testUploadSyncReadWrongState()1016 public void testUploadSyncReadWrongState() throws Exception { 1017 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1018 String url = "url"; 1019 String body = "test"; 1020 callback.setAutoAdvance(false); 1021 FakeUrlRequest.Builder builder = 1022 (FakeUrlRequest.Builder) 1023 mFakeCronetEngine.newUrlRequestBuilder( 1024 url, callback, callback.getExecutor()); 1025 TestUploadDataProvider dataProvider = 1026 new TestUploadDataProvider( 1027 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1028 1029 // Add a redirect response so the request keeps the UploadDataProvider open while waiting 1030 // to follow the redirect. 1031 mFakeCronetController.addRedirectResponse("newUrl", url); 1032 dataProvider.addRead(body.getBytes()); 1033 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1034 builder.addHeader("Content-Type", "useless/string"); 1035 FakeUrlRequest request = (FakeUrlRequest) builder.build(); 1036 request.start(); 1037 callback.waitForNextStep(); 1038 1039 IllegalStateException e = 1040 assertThrows( 1041 IllegalStateException.class, 1042 () -> { 1043 synchronized (request.mLock) { 1044 request.mFakeDataSink.onReadSucceeded(false); 1045 } 1046 }); 1047 1048 assertThat(e) 1049 .hasMessageThat() 1050 .isEqualTo("onReadSucceeded() called when not awaiting a read result; in state: 2"); 1051 request.cancel(); 1052 } 1053 1054 @Test 1055 @SmallTest testUploadSyncRewindWrongState()1056 public void testUploadSyncRewindWrongState() throws Exception { 1057 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1058 String url = "url"; 1059 String body = "test"; 1060 callback.setAutoAdvance(false); 1061 FakeUrlRequest.Builder builder = 1062 (FakeUrlRequest.Builder) 1063 mFakeCronetEngine.newUrlRequestBuilder( 1064 url, callback, callback.getExecutor()); 1065 TestUploadDataProvider dataProvider = 1066 new TestUploadDataProvider( 1067 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1068 1069 // Add a redirect response so the request keeps the UploadDataProvider open while waiting 1070 // to follow the redirect. 1071 mFakeCronetController.addRedirectResponse("newUrl", url); 1072 dataProvider.addRead(body.getBytes()); 1073 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1074 builder.addHeader("Content-Type", "useless/string"); 1075 FakeUrlRequest request = (FakeUrlRequest) builder.build(); 1076 request.start(); 1077 callback.waitForNextStep(); 1078 1079 IllegalStateException e = 1080 assertThrows( 1081 IllegalStateException.class, 1082 () -> { 1083 synchronized (request.mLock) { 1084 request.mFakeDataSink.onRewindSucceeded(); 1085 } 1086 }); 1087 assertThat(e) 1088 .hasMessageThat() 1089 .isEqualTo("onRewindSucceeded() called when not awaiting a rewind; in state: 2"); 1090 request.cancel(); 1091 } 1092 1093 @Test 1094 @SmallTest testUploadMultiplePiecesSync()1095 public void testUploadMultiplePiecesSync() throws Exception { 1096 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1097 String url = "url"; 1098 FakeUrlRequest.Builder builder = 1099 (FakeUrlRequest.Builder) 1100 mFakeCronetEngine.newUrlRequestBuilder( 1101 url, callback, callback.getExecutor()); 1102 TestUploadDataProvider dataProvider = 1103 new TestUploadDataProvider( 1104 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1105 1106 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1107 dataProvider.addRead("Y".getBytes()); 1108 dataProvider.addRead("et ".getBytes()); 1109 dataProvider.addRead("another ".getBytes()); 1110 dataProvider.addRead("test".getBytes()); 1111 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1112 builder.addHeader("Content-Type", "useless/string"); 1113 builder.build().start(); 1114 callback.blockForDone(); 1115 dataProvider.assertClosed(); 1116 1117 assertThat(dataProvider.getUploadedLength()).isEqualTo(16); 1118 assertThat(dataProvider.getNumReadCalls()).isEqualTo(4); 1119 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1120 1121 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1122 assertThat(callback.mResponseAsString).isEqualTo("Yet another test"); 1123 } 1124 1125 @Test 1126 @SmallTest testUploadMultiplePiecesAsync()1127 public void testUploadMultiplePiecesAsync() throws Exception { 1128 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1129 String url = "url"; 1130 FakeUrlRequest.Builder builder = 1131 (FakeUrlRequest.Builder) 1132 mFakeCronetEngine.newUrlRequestBuilder( 1133 url, callback, callback.getExecutor()); 1134 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1135 TestUploadDataProvider dataProvider = 1136 new TestUploadDataProvider( 1137 TestUploadDataProvider.SuccessCallbackMode.ASYNC, callback.getExecutor()); 1138 dataProvider.addRead("Y".getBytes()); 1139 dataProvider.addRead("et ".getBytes()); 1140 dataProvider.addRead("another ".getBytes()); 1141 dataProvider.addRead("test".getBytes()); 1142 1143 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1144 builder.addHeader("Content-Type", "useless/string"); 1145 builder.build().start(); 1146 callback.blockForDone(); 1147 dataProvider.assertClosed(); 1148 1149 assertThat(dataProvider.getUploadedLength()).isEqualTo(16); 1150 assertThat(dataProvider.getNumReadCalls()).isEqualTo(4); 1151 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1152 1153 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1154 assertThat(callback.mResponseAsString).isEqualTo("Yet another test"); 1155 } 1156 1157 @Test 1158 @SmallTest testUploadChangesDefaultMethod()1159 public void testUploadChangesDefaultMethod() throws Exception { 1160 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1161 String url = "url"; 1162 FakeUrlRequest.Builder builder = 1163 (FakeUrlRequest.Builder) 1164 mFakeCronetEngine.newUrlRequestBuilder( 1165 url, callback, callback.getExecutor()); 1166 mFakeCronetController.addResponseMatcher( 1167 new ResponseMatcher() { 1168 @Override 1169 public FakeUrlResponse getMatchingResponse( 1170 String url, 1171 String httpMethod, 1172 List<Map.Entry<String, String>> headers, 1173 byte[] body) { 1174 return new FakeUrlResponse.Builder() 1175 .setResponseBody(httpMethod.getBytes()) 1176 .build(); 1177 } 1178 }); 1179 TestUploadDataProvider dataProvider = 1180 new TestUploadDataProvider( 1181 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1182 dataProvider.addRead("test".getBytes()); 1183 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1184 builder.addHeader("Content-Type", "useless/string"); 1185 builder.build().start(); 1186 callback.blockForDone(); 1187 dataProvider.assertClosed(); 1188 1189 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1190 assertThat(callback.mResponseAsString).isEqualTo("POST"); 1191 } 1192 1193 @Test 1194 @SmallTest testUploadWithSetMethod()1195 public void testUploadWithSetMethod() throws Exception { 1196 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1197 String url = "url"; 1198 FakeUrlRequest.Builder builder = 1199 (FakeUrlRequest.Builder) 1200 mFakeCronetEngine.newUrlRequestBuilder( 1201 url, callback, callback.getExecutor()); 1202 mFakeCronetController.addResponseMatcher( 1203 new ResponseMatcher() { 1204 @Override 1205 public FakeUrlResponse getMatchingResponse( 1206 String url, 1207 String httpMethod, 1208 List<Map.Entry<String, String>> headers, 1209 byte[] body) { 1210 return new FakeUrlResponse.Builder() 1211 .setResponseBody(httpMethod.getBytes()) 1212 .build(); 1213 } 1214 }); 1215 final String method = "PUT"; 1216 builder.setHttpMethod(method); 1217 1218 TestUploadDataProvider dataProvider = 1219 new TestUploadDataProvider( 1220 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1221 dataProvider.addRead("test".getBytes()); 1222 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1223 builder.addHeader("Content-Type", "useless/string"); 1224 builder.build().start(); 1225 callback.blockForDone(); 1226 dataProvider.assertClosed(); 1227 1228 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1229 assertThat(callback.mResponseAsString).isEqualTo("PUT"); 1230 } 1231 1232 @Test 1233 @SmallTest testUploadRedirectSync()1234 public void testUploadRedirectSync() throws Exception { 1235 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1236 String redirectUrl = "redirectUrl"; 1237 String echoBodyUrl = "echobody"; 1238 FakeUrlRequest.Builder builder = 1239 (FakeUrlRequest.Builder) 1240 mFakeCronetEngine.newUrlRequestBuilder( 1241 redirectUrl, callback, callback.getExecutor()); 1242 mFakeCronetController.addRedirectResponse(echoBodyUrl, redirectUrl); 1243 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher(echoBodyUrl)); 1244 1245 TestUploadDataProvider dataProvider = 1246 new TestUploadDataProvider( 1247 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1248 dataProvider.addRead("test".getBytes()); 1249 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1250 builder.addHeader("Content-Type", "useless/string"); 1251 builder.build().start(); 1252 callback.blockForDone(); 1253 dataProvider.assertClosed(); 1254 1255 // 1 read call before the rewind, 1 after. 1256 assertThat(dataProvider.getNumReadCalls()).isEqualTo(2); 1257 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(1); 1258 1259 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1260 assertThat(callback.mResponseAsString).isEqualTo("test"); 1261 } 1262 1263 @Test 1264 @SmallTest testUploadRedirectAsync()1265 public void testUploadRedirectAsync() throws Exception { 1266 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1267 String redirectUrl = "redirectUrl"; 1268 String echoBodyUrl = "echobody"; 1269 FakeUrlRequest.Builder builder = 1270 (FakeUrlRequest.Builder) 1271 mFakeCronetEngine.newUrlRequestBuilder( 1272 redirectUrl, callback, callback.getExecutor()); 1273 mFakeCronetController.addRedirectResponse(echoBodyUrl, redirectUrl); 1274 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher(echoBodyUrl)); 1275 1276 TestUploadDataProvider dataProvider = 1277 new TestUploadDataProvider( 1278 TestUploadDataProvider.SuccessCallbackMode.ASYNC, callback.getExecutor()); 1279 dataProvider.addRead("test".getBytes()); 1280 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1281 builder.addHeader("Content-Type", "useless/string"); 1282 builder.build().start(); 1283 callback.blockForDone(); 1284 dataProvider.assertClosed(); 1285 1286 // 1 read call before the rewind, 1 after. 1287 assertThat(dataProvider.getNumReadCalls()).isEqualTo(2); 1288 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(1); 1289 1290 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1291 assertThat(callback.mResponseAsString).isEqualTo("test"); 1292 } 1293 1294 @Test 1295 @SmallTest testUploadWithBadLength()1296 public void testUploadWithBadLength() throws Exception { 1297 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1298 String url = "url"; 1299 FakeUrlRequest.Builder builder = 1300 (FakeUrlRequest.Builder) 1301 mFakeCronetEngine.newUrlRequestBuilder( 1302 url, callback, callback.getExecutor()); 1303 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1304 1305 TestUploadDataProvider dataProvider = 1306 new TestUploadDataProvider( 1307 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()) { 1308 @Override 1309 public long getLength() throws IOException { 1310 return 1; 1311 } 1312 1313 @Override 1314 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) 1315 throws IOException { 1316 byteBuffer.put("12".getBytes()); 1317 uploadDataSink.onReadSucceeded(false); 1318 } 1319 }; 1320 1321 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1322 builder.addHeader("Content-Type", "useless/string"); 1323 builder.build().start(); 1324 callback.blockForDone(); 1325 dataProvider.assertClosed(); 1326 1327 assertThat(callback.mError) 1328 .hasMessageThat() 1329 .contains("Exception received from UploadDataProvider"); 1330 assertThat(callback.mError) 1331 .hasCauseThat() 1332 .hasMessageThat() 1333 .contains("Read upload data length 2 exceeds expected length 1"); 1334 assertThat(callback.getResponseInfo()).isNull(); 1335 } 1336 1337 @Test 1338 @SmallTest testUploadWithBadLengthBufferAligned()1339 public void testUploadWithBadLengthBufferAligned() throws Exception { 1340 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1341 String url = "url"; 1342 FakeUrlRequest.Builder builder = 1343 (FakeUrlRequest.Builder) 1344 mFakeCronetEngine.newUrlRequestBuilder( 1345 url, callback, callback.getExecutor()); 1346 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1347 1348 TestUploadDataProvider dataProvider = 1349 new TestUploadDataProvider( 1350 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()) { 1351 @Override 1352 public long getLength() throws IOException { 1353 return 8191; 1354 } 1355 1356 @Override 1357 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) 1358 throws IOException { 1359 byteBuffer.put("0123456789abcdef".getBytes()); 1360 uploadDataSink.onReadSucceeded(false); 1361 } 1362 }; 1363 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1364 builder.addHeader("Content-Type", "useless/string"); 1365 builder.build().start(); 1366 callback.blockForDone(); 1367 dataProvider.assertClosed(); 1368 assertThat(callback.mError) 1369 .hasMessageThat() 1370 .contains("Exception received from UploadDataProvider"); 1371 assertThat(callback.mError) 1372 .hasCauseThat() 1373 .hasMessageThat() 1374 .contains("Read upload data length 8192 exceeds expected length 8191"); 1375 assertThat(callback.getResponseInfo()).isNull(); 1376 } 1377 1378 @Test 1379 @SmallTest testUploadLengthFailSync()1380 public void testUploadLengthFailSync() throws Exception { 1381 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1382 String url = "url"; 1383 FakeUrlRequest.Builder builder = 1384 (FakeUrlRequest.Builder) 1385 mFakeCronetEngine.newUrlRequestBuilder( 1386 url, callback, callback.getExecutor()); 1387 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1388 1389 TestUploadDataProvider dataProvider = 1390 new TestUploadDataProvider( 1391 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1392 dataProvider.setLengthFailure(); 1393 // This will never be read, but if the length is 0, read may never be 1394 // called. 1395 dataProvider.addRead("test".getBytes()); 1396 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1397 builder.addHeader("Content-Type", "useless/string"); 1398 builder.build().start(); 1399 callback.blockForDone(); 1400 dataProvider.assertClosed(); 1401 1402 assertThat(dataProvider.getNumReadCalls()).isEqualTo(0); 1403 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1404 1405 assertThat(callback.mError) 1406 .hasMessageThat() 1407 .contains("Exception received from UploadDataProvider"); 1408 assertThat(callback.mError).hasCauseThat().hasMessageThat().contains("Sync length failure"); 1409 assertThat(callback.getResponseInfo()).isNull(); 1410 } 1411 1412 @Test 1413 @SmallTest testUploadReadFailSync()1414 public void testUploadReadFailSync() throws Exception { 1415 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1416 String url = "url"; 1417 FakeUrlRequest.Builder builder = 1418 (FakeUrlRequest.Builder) 1419 mFakeCronetEngine.newUrlRequestBuilder( 1420 url, callback, callback.getExecutor()); 1421 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1422 1423 TestUploadDataProvider dataProvider = 1424 new TestUploadDataProvider( 1425 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1426 dataProvider.setReadFailure( 1427 /* readFailIndex= */ 0, TestUploadDataProvider.FailMode.CALLBACK_SYNC); 1428 // This will never be read, but if the length is 0, read may never be 1429 // called. 1430 dataProvider.addRead("test".getBytes()); 1431 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1432 builder.addHeader("Content-Type", "useless/string"); 1433 builder.build().start(); 1434 callback.blockForDone(); 1435 dataProvider.assertClosed(); 1436 1437 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1438 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1439 1440 assertThat(callback.mError) 1441 .hasMessageThat() 1442 .contains("Exception received from UploadDataProvider"); 1443 assertThat(callback.mError).hasCauseThat().hasMessageThat().contains("Sync read failure"); 1444 assertThat(callback.getResponseInfo()).isNull(); 1445 } 1446 1447 @Test 1448 @SmallTest testUploadReadFailAsync()1449 public void testUploadReadFailAsync() throws Exception { 1450 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1451 String url = "url"; 1452 FakeUrlRequest.Builder builder = 1453 (FakeUrlRequest.Builder) 1454 mFakeCronetEngine.newUrlRequestBuilder( 1455 url, callback, callback.getExecutor()); 1456 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1457 1458 TestUploadDataProvider dataProvider = 1459 new TestUploadDataProvider( 1460 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1461 dataProvider.setReadFailure( 1462 /* readFailIndex= */ 0, TestUploadDataProvider.FailMode.CALLBACK_ASYNC); 1463 // This will never be read, but if the length is 0, read may never be 1464 // called. 1465 dataProvider.addRead("test".getBytes()); 1466 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1467 builder.addHeader("Content-Type", "useless/string"); 1468 builder.build().start(); 1469 callback.blockForDone(); 1470 dataProvider.assertClosed(); 1471 1472 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1473 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1474 1475 assertThat(callback.mError) 1476 .hasMessageThat() 1477 .contains("Exception received from UploadDataProvider"); 1478 assertThat(callback.mError).hasCauseThat().hasMessageThat().contains("Async read failure"); 1479 assertThat(callback.getResponseInfo()).isNull(); 1480 } 1481 1482 @Test 1483 @SmallTest testUploadReadFailThrown()1484 public void testUploadReadFailThrown() throws Exception { 1485 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1486 String url = "url"; 1487 FakeUrlRequest.Builder builder = 1488 (FakeUrlRequest.Builder) 1489 mFakeCronetEngine.newUrlRequestBuilder( 1490 url, callback, callback.getExecutor()); 1491 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1492 1493 TestUploadDataProvider dataProvider = 1494 new TestUploadDataProvider( 1495 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1496 dataProvider.setReadFailure(/* readFailIndex= */ 0, TestUploadDataProvider.FailMode.THROWN); 1497 // This will never be read, but if the length is 0, read may never be 1498 // called. 1499 dataProvider.addRead("test".getBytes()); 1500 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1501 builder.addHeader("Content-Type", "useless/string"); 1502 builder.build().start(); 1503 callback.blockForDone(); 1504 dataProvider.assertClosed(); 1505 1506 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1507 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1508 1509 assertThat(callback.mError) 1510 .hasMessageThat() 1511 .contains("Exception received from UploadDataProvider"); 1512 assertThat(callback.mError).hasCauseThat().hasMessageThat().contains("Thrown read failure"); 1513 assertThat(callback.getResponseInfo()).isNull(); 1514 } 1515 1516 /** This test uses a direct executor for upload, and non direct for callbacks */ 1517 @Test 1518 @SmallTest testDirectExecutorUploadProhibitedByDefault()1519 public void testDirectExecutorUploadProhibitedByDefault() throws Exception { 1520 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1521 Executor myExecutor = 1522 new Executor() { 1523 @Override 1524 public void execute(Runnable command) { 1525 command.run(); 1526 } 1527 }; 1528 String url = "url"; 1529 FakeUrlRequest.Builder builder = 1530 (FakeUrlRequest.Builder) 1531 mFakeCronetEngine.newUrlRequestBuilder( 1532 url, callback, callback.getExecutor()); 1533 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1534 1535 TestUploadDataProvider dataProvider = 1536 new TestUploadDataProvider( 1537 TestUploadDataProvider.SuccessCallbackMode.SYNC, myExecutor); 1538 // This will never be read, but if the length is 0, read may never be 1539 // called. 1540 dataProvider.addRead("test".getBytes()); 1541 builder.setUploadDataProvider(dataProvider, myExecutor); 1542 builder.addHeader("Content-Type", "useless/string"); 1543 builder.build().start(); 1544 callback.blockForDone(); 1545 1546 assertThat(dataProvider.getNumReadCalls()).isEqualTo(0); 1547 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1548 1549 assertThat(callback.mError) 1550 .hasMessageThat() 1551 .contains("Exception received from UploadDataProvider"); 1552 assertThat(callback.mError) 1553 .hasCauseThat() 1554 .hasMessageThat() 1555 .contains("Inline execution is prohibited for this request"); 1556 assertThat(callback.getResponseInfo()).isNull(); 1557 } 1558 1559 /** This test uses a direct executor for callbacks, and non direct for upload */ 1560 @Test 1561 @SmallTest testDirectExecutorProhibitedByDefault()1562 public void testDirectExecutorProhibitedByDefault() throws Exception { 1563 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1564 // Everything submitted to this executor will be executed immediately on the thread 1565 // that submitted the Runnable (blocking it until the runnable completes) 1566 Executor directExecutor = 1567 new Executor() { 1568 @Override 1569 public void execute(Runnable command) { 1570 command.run(); 1571 } 1572 }; 1573 String url = "url"; 1574 FakeUrlRequest.Builder builder = 1575 (FakeUrlRequest.Builder) 1576 mFakeCronetEngine.newUrlRequestBuilder(url, callback, directExecutor); 1577 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1578 1579 TestUploadDataProvider dataProvider = 1580 new TestUploadDataProvider( 1581 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1582 // This will never be read, but if the length is 0, read may never be 1583 // called. 1584 dataProvider.addRead("test".getBytes()); 1585 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1586 builder.addHeader("Content-Type", "useless/string"); 1587 builder.build().start(); 1588 callback.blockForDone(); 1589 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1590 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(0); 1591 assertThat(callback.mError).hasMessageThat().contains("Exception posting task to executor"); 1592 assertThat(callback.mError) 1593 .hasCauseThat() 1594 .hasMessageThat() 1595 .contains("Inline execution is prohibited for this request"); 1596 assertThat(callback.getResponseInfo()).isNull(); 1597 dataProvider.assertClosed(); 1598 } 1599 1600 @Test 1601 @SmallTest testDirectExecutorAllowed()1602 public void testDirectExecutorAllowed() throws Exception { 1603 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1604 callback.setAllowDirectExecutor(true); 1605 Executor myExecutor = 1606 new Executor() { 1607 @Override 1608 public void execute(Runnable command) { 1609 command.run(); 1610 } 1611 }; 1612 String url = "url"; 1613 FakeUrlRequest.Builder builder = 1614 (FakeUrlRequest.Builder) 1615 mFakeCronetEngine.newUrlRequestBuilder( 1616 url, callback, callback.getExecutor()); 1617 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1618 UploadDataProvider dataProvider = UploadDataProviders.create("test".getBytes()); 1619 builder.setUploadDataProvider(dataProvider, myExecutor); 1620 builder.addHeader("Content-Type", "useless/string"); 1621 builder.allowDirectExecutor(); 1622 builder.build().start(); 1623 callback.blockForDone(); 1624 1625 if (callback.mOnErrorCalled) { 1626 throw callback.mError; 1627 } 1628 1629 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 1630 assertThat(callback.mResponseAsString).isEqualTo("test"); 1631 } 1632 1633 @Test 1634 @SmallTest testUploadRewindFailSync()1635 public void testUploadRewindFailSync() throws Exception { 1636 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1637 String redirectUrl = "redirectUrl"; 1638 String echoBodyUrl = "echobody"; 1639 FakeUrlRequest.Builder builder = 1640 (FakeUrlRequest.Builder) 1641 mFakeCronetEngine.newUrlRequestBuilder( 1642 redirectUrl, callback, callback.getExecutor()); 1643 mFakeCronetController.addRedirectResponse(echoBodyUrl, redirectUrl); 1644 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher(echoBodyUrl)); 1645 1646 TestUploadDataProvider dataProvider = 1647 new TestUploadDataProvider( 1648 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1649 dataProvider.setRewindFailure(TestUploadDataProvider.FailMode.CALLBACK_SYNC); 1650 dataProvider.addRead("test".getBytes()); 1651 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1652 builder.addHeader("Content-Type", "useless/string"); 1653 builder.build().start(); 1654 callback.blockForDone(); 1655 dataProvider.assertClosed(); 1656 1657 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1658 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(1); 1659 1660 assertThat(callback.mError) 1661 .hasMessageThat() 1662 .contains("Exception received from UploadDataProvider"); 1663 assertThat(callback.mError).hasCauseThat().hasMessageThat().contains("Sync rewind failure"); 1664 assertThat(callback.getResponseInfo()).isNull(); 1665 } 1666 1667 @Test 1668 @SmallTest testUploadRewindFailAsync()1669 public void testUploadRewindFailAsync() throws Exception { 1670 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1671 String redirectUrl = "redirectUrl"; 1672 String echoBodyUrl = "echobody"; 1673 FakeUrlRequest.Builder builder = 1674 (FakeUrlRequest.Builder) 1675 mFakeCronetEngine.newUrlRequestBuilder( 1676 redirectUrl, callback, callback.getExecutor()); 1677 mFakeCronetController.addRedirectResponse(echoBodyUrl, redirectUrl); 1678 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher(echoBodyUrl)); 1679 1680 TestUploadDataProvider dataProvider = 1681 new TestUploadDataProvider( 1682 TestUploadDataProvider.SuccessCallbackMode.ASYNC, callback.getExecutor()); 1683 dataProvider.setRewindFailure(TestUploadDataProvider.FailMode.CALLBACK_ASYNC); 1684 dataProvider.addRead("test".getBytes()); 1685 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1686 builder.addHeader("Content-Type", "useless/string"); 1687 builder.build().start(); 1688 callback.blockForDone(); 1689 dataProvider.assertClosed(); 1690 1691 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1692 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(1); 1693 1694 assertThat(callback.mError) 1695 .hasMessageThat() 1696 .contains("Exception received from UploadDataProvider"); 1697 assertThat(callback.mError) 1698 .hasCauseThat() 1699 .hasMessageThat() 1700 .contains("Async rewind failure"); 1701 assertThat(callback.getResponseInfo()).isNull(); 1702 } 1703 1704 @Test 1705 @SmallTest testUploadRewindFailThrown()1706 public void testUploadRewindFailThrown() throws Exception { 1707 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1708 String redirectUrl = "redirectUrl"; 1709 String echoBodyUrl = "echobody"; 1710 FakeUrlRequest.Builder builder = 1711 (FakeUrlRequest.Builder) 1712 mFakeCronetEngine.newUrlRequestBuilder( 1713 redirectUrl, callback, callback.getExecutor()); 1714 mFakeCronetController.addRedirectResponse(echoBodyUrl, redirectUrl); 1715 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher(echoBodyUrl)); 1716 1717 TestUploadDataProvider dataProvider = 1718 new TestUploadDataProvider( 1719 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1720 dataProvider.setRewindFailure(TestUploadDataProvider.FailMode.THROWN); 1721 dataProvider.addRead("test".getBytes()); 1722 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1723 builder.addHeader("Content-Type", "useless/string"); 1724 builder.build().start(); 1725 callback.blockForDone(); 1726 dataProvider.assertClosed(); 1727 1728 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1729 assertThat(dataProvider.getNumRewindCalls()).isEqualTo(1); 1730 1731 assertThat(callback.mError) 1732 .hasMessageThat() 1733 .contains("Exception received from UploadDataProvider"); 1734 assertThat(callback.mError) 1735 .hasCauseThat() 1736 .hasMessageThat() 1737 .contains("Thrown rewind failure"); 1738 assertThat(callback.getResponseInfo()).isNull(); 1739 } 1740 1741 @Test 1742 @SmallTest testUploadChunked()1743 public void testUploadChunked() throws Exception { 1744 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1745 String url = "url"; 1746 FakeUrlRequest.Builder builder = 1747 (FakeUrlRequest.Builder) 1748 mFakeCronetEngine.newUrlRequestBuilder( 1749 url, callback, callback.getExecutor()); 1750 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1751 1752 TestUploadDataProvider dataProvider = 1753 new TestUploadDataProvider( 1754 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1755 dataProvider.addRead("test hello".getBytes()); 1756 dataProvider.setChunked(true); 1757 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1758 builder.addHeader("Content-Type", "useless/string"); 1759 1760 assertThat(dataProvider.getUploadedLength()).isEqualTo(-1); 1761 1762 builder.build().start(); 1763 callback.blockForDone(); 1764 dataProvider.assertClosed(); 1765 1766 // 1 read call for one data chunk. 1767 assertThat(dataProvider.getNumReadCalls()).isEqualTo(1); 1768 assertThat(callback.mResponseAsString).isEqualTo("test hello"); 1769 } 1770 1771 @Test 1772 @SmallTest testUploadChunkedLastReadZeroLengthBody()1773 public void testUploadChunkedLastReadZeroLengthBody() throws Exception { 1774 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1775 String url = "url"; 1776 FakeUrlRequest.Builder builder = 1777 (FakeUrlRequest.Builder) 1778 mFakeCronetEngine.newUrlRequestBuilder( 1779 url, callback, callback.getExecutor()); 1780 mFakeCronetController.addResponseMatcher(new EchoBodyResponseMatcher()); 1781 1782 TestUploadDataProvider dataProvider = 1783 new TestUploadDataProvider( 1784 TestUploadDataProvider.SuccessCallbackMode.SYNC, callback.getExecutor()); 1785 // Add 3 reads. The last read has a 0-length body. 1786 dataProvider.addRead("hello there".getBytes()); 1787 dataProvider.addRead("!".getBytes()); 1788 dataProvider.addRead("".getBytes()); 1789 dataProvider.setChunked(true); 1790 builder.setUploadDataProvider(dataProvider, callback.getExecutor()); 1791 builder.addHeader("Content-Type", "useless/string"); 1792 1793 assertThat(dataProvider.getUploadedLength()).isEqualTo(-1); 1794 1795 builder.build().start(); 1796 callback.blockForDone(); 1797 dataProvider.assertClosed(); 1798 1799 // 2 read call for the first two data chunks, and 1 for final chunk. 1800 assertThat(dataProvider.getNumReadCalls()).isEqualTo(3); 1801 assertThat(callback.mResponseAsString).isEqualTo("hello there!"); 1802 } 1803 1804 @Test 1805 @SmallTest testCancelBeforeStart_doesNotCrash()1806 public void testCancelBeforeStart_doesNotCrash() { 1807 // Setup the basic response. 1808 String responseText = "response text"; 1809 String url = "TEST_URL"; 1810 FakeUrlResponse response = 1811 new FakeUrlResponse.Builder().setResponseBody(responseText.getBytes()).build(); 1812 mFakeCronetController.addResponseForUrl(response, url); 1813 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 1814 FakeUrlRequest request = 1815 (FakeUrlRequest) 1816 mFakeCronetEngine 1817 .newUrlRequestBuilder(url, callback, callback.getExecutor()) 1818 .build(); 1819 1820 request.cancel(); 1821 request.start(); 1822 callback.blockForDone(); 1823 1824 assertThat(callback.mResponseStep).isEqualTo(ResponseStep.ON_SUCCEEDED); 1825 } 1826 1827 /** A Cronet callback that does nothing. */ 1828 static class StubCallback extends UrlRequest.Callback { 1829 @Override onRedirectReceived( org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, String s)1830 public void onRedirectReceived( 1831 org.chromium.net.UrlRequest urlRequest, 1832 UrlResponseInfo urlResponseInfo, 1833 String s) {} 1834 1835 @Override onResponseStarted( org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo)1836 public void onResponseStarted( 1837 org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo) {} 1838 1839 @Override onReadCompleted( org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, ByteBuffer byteBuffer)1840 public void onReadCompleted( 1841 org.chromium.net.UrlRequest urlRequest, 1842 UrlResponseInfo urlResponseInfo, 1843 ByteBuffer byteBuffer) {} 1844 1845 @Override onSucceeded( org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo)1846 public void onSucceeded( 1847 org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo) {} 1848 1849 @Override onFailed( org.chromium.net.UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, CronetException e)1850 public void onFailed( 1851 org.chromium.net.UrlRequest urlRequest, 1852 UrlResponseInfo urlResponseInfo, 1853 CronetException e) {} 1854 } 1855 } 1856