1 // Copyright 2016 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; 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 android.os.ConditionVariable; 13 14 import androidx.test.ext.junit.runners.AndroidJUnit4; 15 import androidx.test.filters.SmallTest; 16 17 import org.junit.After; 18 import org.junit.Before; 19 import org.junit.Rule; 20 import org.junit.Test; 21 import org.junit.runner.RunWith; 22 23 import org.chromium.base.test.util.DoNotBatch; 24 import org.chromium.net.CronetTestRule.CronetImplementation; 25 import org.chromium.net.CronetTestRule.IgnoreFor; 26 import org.chromium.net.CronetTestRule.RequiresMinApi; 27 import org.chromium.net.MetricsTestUtil.TestExecutor; 28 import org.chromium.net.impl.CronetMetrics; 29 30 import java.util.ArrayList; 31 import java.util.Date; 32 import java.util.List; 33 import java.util.concurrent.Executor; 34 import java.util.concurrent.RejectedExecutionException; 35 import java.util.concurrent.atomic.AtomicBoolean; 36 37 /** Test RequestFinishedInfo.Listener and the metrics information it provides. */ 38 @DoNotBatch(reason = "crbug/1459563") 39 @RunWith(AndroidJUnit4.class) 40 @IgnoreFor( 41 implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, 42 reason = "Fallback and AOSP implementations do not support RequestFinishedListeners") 43 public class RequestFinishedInfoTest { 44 @Rule public final CronetTestRule mTestRule = CronetTestRule.withAutomaticEngineStartup(); 45 46 private String mUrl; 47 48 // A subclass of TestRequestFinishedListener to additionally assert that UrlRequest.Callback's 49 // terminal callbacks have been invoked at the time of onRequestFinished(). 50 // See crbug.com/710877. 51 private static class AssertCallbackDoneRequestFinishedListener 52 extends TestRequestFinishedListener { 53 private final TestUrlRequestCallback mCallback; 54 AssertCallbackDoneRequestFinishedListener(TestUrlRequestCallback callback)55 public AssertCallbackDoneRequestFinishedListener(TestUrlRequestCallback callback) { 56 // Use same executor as request callback to verify stable call order. 57 super(callback.getExecutor()); 58 mCallback = callback; 59 } 60 61 @Override onRequestFinished(RequestFinishedInfo requestInfo)62 public void onRequestFinished(RequestFinishedInfo requestInfo) { 63 assertThat(mCallback.isDone()).isTrue(); 64 super.onRequestFinished(requestInfo); 65 } 66 } 67 ; 68 69 @Before setUp()70 public void setUp() throws Exception { 71 NativeTestServer.startNativeTestServer(mTestRule.getTestFramework().getContext()); 72 mUrl = NativeTestServer.getFileURL("/echo?status=200"); 73 } 74 75 @After tearDown()76 public void tearDown() throws Exception { 77 NativeTestServer.shutdownNativeTestServer(); 78 } 79 80 static class DirectExecutor implements Executor { 81 private ConditionVariable mBlock = new ConditionVariable(); 82 83 @Override execute(Runnable task)84 public void execute(Runnable task) { 85 task.run(); 86 mBlock.open(); 87 } 88 blockUntilDone()89 public void blockUntilDone() { 90 mBlock.block(); 91 } 92 } 93 94 static class ThreadExecutor implements Executor { 95 private List<Thread> mThreads = new ArrayList<Thread>(); 96 97 @Override execute(Runnable task)98 public void execute(Runnable task) { 99 Thread newThread = new Thread(task); 100 mThreads.add(newThread); 101 newThread.start(); 102 } 103 joinAll()104 public void joinAll() throws InterruptedException { 105 for (Thread thread : mThreads) { 106 thread.join(); 107 } 108 } 109 } 110 111 @Test 112 @SmallTest 113 @SuppressWarnings("deprecation") testRequestFinishedListener()114 public void testRequestFinishedListener() throws Exception { 115 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 116 mTestRule 117 .getTestFramework() 118 .getEngine() 119 .addRequestFinishedListener(requestFinishedListener); 120 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 121 ExperimentalUrlRequest.Builder urlRequestBuilder = 122 (ExperimentalUrlRequest.Builder) 123 mTestRule 124 .getTestFramework() 125 .getEngine() 126 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 127 Date startTime = new Date(); 128 urlRequestBuilder 129 .addRequestAnnotation("request annotation") 130 .addRequestAnnotation(this) 131 .build() 132 .start(); 133 callback.blockForDone(); 134 requestFinishedListener.blockUntilDone(); 135 Date endTime = new Date(); 136 137 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 138 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 139 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 140 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 141 assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); 142 } 143 144 @Test 145 @SmallTest 146 @SuppressWarnings("deprecation") testRequestFinishedListenerDirectExecutor()147 public void testRequestFinishedListenerDirectExecutor() throws Exception { 148 DirectExecutor testExecutor = new DirectExecutor(); 149 TestRequestFinishedListener requestFinishedListener = 150 new TestRequestFinishedListener(testExecutor); 151 mTestRule 152 .getTestFramework() 153 .getEngine() 154 .addRequestFinishedListener(requestFinishedListener); 155 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 156 ExperimentalUrlRequest.Builder urlRequestBuilder = 157 (ExperimentalUrlRequest.Builder) 158 mTestRule 159 .getTestFramework() 160 .getEngine() 161 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 162 Date startTime = new Date(); 163 urlRequestBuilder 164 .addRequestAnnotation("request annotation") 165 .addRequestAnnotation(this) 166 .build() 167 .start(); 168 callback.blockForDone(); 169 // Block on the executor, not the listener, since blocking on the listener doesn't work when 170 // it's created with a non-default executor. 171 testExecutor.blockUntilDone(); 172 Date endTime = new Date(); 173 174 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 175 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 176 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 177 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 178 assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); 179 } 180 181 @Test 182 @SmallTest 183 @SuppressWarnings("deprecation") testRequestFinishedListenerDifferentThreads()184 public void testRequestFinishedListenerDifferentThreads() throws Exception { 185 TestRequestFinishedListener firstListener = new TestRequestFinishedListener(); 186 TestRequestFinishedListener secondListener = new TestRequestFinishedListener(); 187 mTestRule.getTestFramework().getEngine().addRequestFinishedListener(firstListener); 188 mTestRule.getTestFramework().getEngine().addRequestFinishedListener(secondListener); 189 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 190 ExperimentalUrlRequest.Builder urlRequestBuilder = 191 (ExperimentalUrlRequest.Builder) 192 mTestRule 193 .getTestFramework() 194 .getEngine() 195 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 196 Date startTime = new Date(); 197 urlRequestBuilder 198 .addRequestAnnotation("request annotation") 199 .addRequestAnnotation(this) 200 .build() 201 .start(); 202 callback.blockForDone(); 203 firstListener.blockUntilDone(); 204 secondListener.blockUntilDone(); 205 Date endTime = new Date(); 206 207 RequestFinishedInfo firstRequestInfo = firstListener.getRequestInfo(); 208 RequestFinishedInfo secondRequestInfo = secondListener.getRequestInfo(); 209 210 MetricsTestUtil.checkRequestFinishedInfo(firstRequestInfo, mUrl, startTime, endTime); 211 assertThat(firstRequestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 212 MetricsTestUtil.checkHasConnectTiming( 213 firstRequestInfo.getMetrics(), startTime, endTime, false); 214 215 MetricsTestUtil.checkRequestFinishedInfo(secondRequestInfo, mUrl, startTime, endTime); 216 assertThat(secondRequestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 217 MetricsTestUtil.checkHasConnectTiming( 218 secondRequestInfo.getMetrics(), startTime, endTime, false); 219 220 assertThat(firstRequestInfo.getAnnotations()).containsExactly("request annotation", this); 221 assertThat(secondRequestInfo.getAnnotations()).containsExactly("request annotation", this); 222 } 223 224 @Test 225 @SmallTest 226 @SuppressWarnings("deprecation") testRequestFinishedListenerFailedRequest()227 public void testRequestFinishedListenerFailedRequest() throws Exception { 228 String connectionRefusedUrl = "http://127.0.0.1:3"; 229 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 230 mTestRule 231 .getTestFramework() 232 .getEngine() 233 .addRequestFinishedListener(requestFinishedListener); 234 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 235 UrlRequest.Builder urlRequestBuilder = 236 mTestRule 237 .getTestFramework() 238 .getEngine() 239 .newUrlRequestBuilder( 240 connectionRefusedUrl, callback, callback.getExecutor()); 241 Date startTime = new Date(); 242 urlRequestBuilder.build().start(); 243 callback.blockForDone(); 244 assertThat(callback.mOnErrorCalled).isTrue(); 245 requestFinishedListener.blockUntilDone(); 246 Date endTime = new Date(); 247 248 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 249 assertWithMessage("RequestFinishedInfo.Listener must be called") 250 .that(requestInfo) 251 .isNotNull(); 252 assertThat(requestInfo.getUrl()).isEqualTo(connectionRefusedUrl); 253 assertThat(requestInfo.getAnnotations()).isEmpty(); 254 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.FAILED); 255 assertThat(requestInfo.getException()).isNotNull(); 256 assertThat(((NetworkException) requestInfo.getException()).getErrorCode()) 257 .isEqualTo(NetworkException.ERROR_CONNECTION_REFUSED); 258 RequestFinishedInfo.Metrics metrics = requestInfo.getMetrics(); 259 assertWithMessage("RequestFinishedInfo.getMetrics() must not be null") 260 .that(metrics) 261 .isNotNull(); 262 // The failure is occasionally fast enough that time reported is 0, so just check for null 263 assertThat(metrics.getTotalTimeMs()).isNotNull(); 264 assertThat(metrics.getTtfbMs()).isNull(); 265 266 // Check the timing metrics 267 assertThat(metrics.getRequestStart()).isNotNull(); 268 MetricsTestUtil.assertAfter(metrics.getRequestStart(), startTime); 269 MetricsTestUtil.checkNoConnectTiming(metrics); 270 assertThat(metrics.getSendingStart()).isNull(); 271 assertThat(metrics.getSendingEnd()).isNull(); 272 assertThat(metrics.getResponseStart()).isNull(); 273 assertThat(metrics.getRequestEnd()).isNotNull(); 274 MetricsTestUtil.assertAfter(endTime, metrics.getRequestEnd()); 275 MetricsTestUtil.assertAfter(metrics.getRequestEnd(), metrics.getRequestStart()); 276 assertThat(metrics.getSentByteCount()).isEqualTo(0); 277 assertThat(metrics.getReceivedByteCount()).isEqualTo(0); 278 } 279 280 @Test 281 @SmallTest testRequestFinishedListenerThrowInTerminalCallback()282 public void testRequestFinishedListenerThrowInTerminalCallback() throws Exception { 283 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 284 mTestRule 285 .getTestFramework() 286 .getEngine() 287 .addRequestFinishedListener(requestFinishedListener); 288 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 289 callback.setFailure( 290 TestUrlRequestCallback.FailureType.THROW_SYNC, 291 TestUrlRequestCallback.ResponseStep.ON_SUCCEEDED); 292 mTestRule 293 .getTestFramework() 294 .getEngine() 295 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()) 296 .build() 297 .start(); 298 callback.blockForDone(); 299 requestFinishedListener.blockUntilDone(); 300 } 301 302 @Test 303 @SmallTest testRequestFinishedListenerThrowInListener()304 public void testRequestFinishedListenerThrowInListener() throws Exception { 305 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 306 requestFinishedListener.makeListenerThrow(); 307 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 308 mTestRule 309 .getTestFramework() 310 .getEngine() 311 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()) 312 .setRequestFinishedListener(requestFinishedListener) 313 .build() 314 .start(); 315 callback.blockForDone(); 316 // We expect that the exception from the listener will not crash the test. 317 requestFinishedListener.blockUntilDone(); 318 } 319 320 @Test 321 @SmallTest testRequestFinishedListenerThrowInEngineListener()322 public void testRequestFinishedListenerThrowInEngineListener() throws Exception { 323 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 324 requestFinishedListener.makeListenerThrow(); 325 mTestRule 326 .getTestFramework() 327 .getEngine() 328 .addRequestFinishedListener(requestFinishedListener); 329 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 330 mTestRule 331 .getTestFramework() 332 .getEngine() 333 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()) 334 .build() 335 .start(); 336 callback.blockForDone(); 337 // We expect that the exception from the listener will not crash the test. 338 requestFinishedListener.blockUntilDone(); 339 } 340 341 @Test 342 @SmallTest 343 @SuppressWarnings("deprecation") testRequestFinishedListenerRemoved()344 public void testRequestFinishedListenerRemoved() throws Exception { 345 TestExecutor testExecutor = new TestExecutor(); 346 TestRequestFinishedListener requestFinishedListener = 347 new TestRequestFinishedListener(testExecutor); 348 mTestRule 349 .getTestFramework() 350 .getEngine() 351 .addRequestFinishedListener(requestFinishedListener); 352 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 353 UrlRequest.Builder urlRequestBuilder = 354 mTestRule 355 .getTestFramework() 356 .getEngine() 357 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 358 UrlRequest request = urlRequestBuilder.build(); 359 mTestRule 360 .getTestFramework() 361 .getEngine() 362 .removeRequestFinishedListener(requestFinishedListener); 363 request.start(); 364 callback.blockForDone(); 365 testExecutor.runAllTasks(); 366 367 assertWithMessage("RequestFinishedInfo.Listener must not be called") 368 .that(requestFinishedListener.getRequestInfo()) 369 .isNull(); 370 } 371 372 @Test 373 @SmallTest testRequestFinishedListenerCanceledRequest()374 public void testRequestFinishedListenerCanceledRequest() throws Exception { 375 TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); 376 mTestRule 377 .getTestFramework() 378 .getEngine() 379 .addRequestFinishedListener(requestFinishedListener); 380 TestUrlRequestCallback callback = 381 new TestUrlRequestCallback() { 382 @Override 383 public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { 384 super.onResponseStarted(request, info); 385 request.cancel(); 386 } 387 }; 388 ExperimentalUrlRequest.Builder urlRequestBuilder = 389 mTestRule 390 .getTestFramework() 391 .getEngine() 392 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 393 Date startTime = new Date(); 394 urlRequestBuilder 395 .addRequestAnnotation("request annotation") 396 .addRequestAnnotation(this) 397 .build() 398 .start(); 399 callback.blockForDone(); 400 requestFinishedListener.blockUntilDone(); 401 Date endTime = new Date(); 402 403 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 404 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 405 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.CANCELED); 406 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 407 408 assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); 409 } 410 411 private static class RejectAllTasksExecutor implements Executor { 412 @Override execute(Runnable task)413 public void execute(Runnable task) { 414 throw new RejectedExecutionException(); 415 } 416 } 417 418 // Checks that CronetURLRequestAdapter::DestroyOnNetworkThread() doesn't crash when metrics 419 // collection is enabled and the URLRequest hasn't been created. See http://crbug.com/675629. 420 @Test 421 @SmallTest testExceptionInRequestStart()422 public void testExceptionInRequestStart() throws Exception { 423 // The listener in this test shouldn't get any tasks. 424 Executor executor = new RejectAllTasksExecutor(); 425 TestRequestFinishedListener requestFinishedListener = 426 new TestRequestFinishedListener(executor); 427 mTestRule 428 .getTestFramework() 429 .getEngine() 430 .addRequestFinishedListener(requestFinishedListener); 431 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 432 ExperimentalUrlRequest.Builder urlRequestBuilder = 433 mTestRule 434 .getTestFramework() 435 .getEngine() 436 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 437 // Empty headers are invalid and will cause start() to throw an exception. 438 UrlRequest request = urlRequestBuilder.addHeader("", "").build(); 439 IllegalArgumentException e = assertThrows(IllegalArgumentException.class, request::start); 440 assertThat(e).hasMessageThat().isEqualTo("Invalid header with headername: "); 441 } 442 443 @Test 444 @SmallTest testMetricsGetters()445 public void testMetricsGetters() throws Exception { 446 long requestStart = 1; 447 long dnsStart = 2; 448 long dnsEnd = -1; 449 long connectStart = 4; 450 long connectEnd = 5; 451 long sslStart = 6; 452 long sslEnd = 7; 453 long sendingStart = 8; 454 long sendingEnd = 9; 455 long pushStart = 10; 456 long pushEnd = 11; 457 long responseStart = 12; 458 long requestEnd = 13; 459 boolean socketReused = true; 460 long sentByteCount = 14; 461 long receivedByteCount = 15; 462 // Make sure nothing gets reordered inside the Metrics class 463 RequestFinishedInfo.Metrics metrics = 464 new CronetMetrics( 465 requestStart, 466 dnsStart, 467 dnsEnd, 468 connectStart, 469 connectEnd, 470 sslStart, 471 sslEnd, 472 sendingStart, 473 sendingEnd, 474 pushStart, 475 pushEnd, 476 responseStart, 477 requestEnd, 478 socketReused, 479 sentByteCount, 480 receivedByteCount); 481 assertThat(metrics.getRequestStart()).isEqualTo(new Date(requestStart)); 482 // -1 timestamp should translate to null 483 assertThat(metrics.getDnsEnd()).isNull(); 484 assertThat(metrics.getDnsStart()).isEqualTo(new Date(dnsStart)); 485 assertThat(metrics.getConnectStart()).isEqualTo(new Date(connectStart)); 486 assertThat(metrics.getConnectEnd()).isEqualTo(new Date(connectEnd)); 487 assertThat(metrics.getSslStart()).isEqualTo(new Date(sslStart)); 488 assertThat(metrics.getSslEnd()).isEqualTo(new Date(sslEnd)); 489 assertThat(metrics.getPushStart()).isEqualTo(new Date(pushStart)); 490 assertThat(metrics.getPushEnd()).isEqualTo(new Date(pushEnd)); 491 assertThat(metrics.getResponseStart()).isEqualTo(new Date(responseStart)); 492 assertThat(metrics.getRequestEnd()).isEqualTo(new Date(requestEnd)); 493 assertThat(metrics.getSocketReused()).isEqualTo(socketReused); 494 assertThat((long) metrics.getSentByteCount()).isEqualTo(sentByteCount); 495 assertThat((long) metrics.getReceivedByteCount()).isEqualTo(receivedByteCount); 496 } 497 498 @Test 499 @SmallTest 500 @SuppressWarnings("deprecation") testOrderSuccessfulRequest()501 public void testOrderSuccessfulRequest() throws Exception { 502 final TestUrlRequestCallback callback = new TestUrlRequestCallback(); 503 TestRequestFinishedListener requestFinishedListener = 504 new AssertCallbackDoneRequestFinishedListener(callback); 505 mTestRule 506 .getTestFramework() 507 .getEngine() 508 .addRequestFinishedListener(requestFinishedListener); 509 ExperimentalUrlRequest.Builder urlRequestBuilder = 510 (ExperimentalUrlRequest.Builder) 511 mTestRule 512 .getTestFramework() 513 .getEngine() 514 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 515 Date startTime = new Date(); 516 urlRequestBuilder 517 .addRequestAnnotation("request annotation") 518 .addRequestAnnotation(this) 519 .build() 520 .start(); 521 callback.blockForDone(); 522 requestFinishedListener.blockUntilDone(); 523 Date endTime = new Date(); 524 525 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 526 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 527 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 528 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 529 assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); 530 } 531 532 @Test 533 @SmallTest 534 @RequiresMinApi(11) testUpdateAnnotationOnSucceeded()535 public void testUpdateAnnotationOnSucceeded() throws Exception { 536 // The annotation that is updated in onSucceeded() callback. 537 AtomicBoolean requestAnnotation = new AtomicBoolean(false); 538 final TestUrlRequestCallback callback = 539 new TestUrlRequestCallback() { 540 @Override 541 public void onSucceeded(UrlRequest request, UrlResponseInfo info) { 542 // Add processing information to request annotation. 543 requestAnnotation.set(true); 544 super.onSucceeded(request, info); 545 } 546 }; 547 TestRequestFinishedListener requestFinishedListener = 548 new AssertCallbackDoneRequestFinishedListener(callback); 549 ExperimentalUrlRequest.Builder urlRequestBuilder = 550 (ExperimentalUrlRequest.Builder) 551 mTestRule 552 .getTestFramework() 553 .getEngine() 554 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 555 Date startTime = new Date(); 556 urlRequestBuilder 557 .addRequestAnnotation(requestAnnotation) 558 .setRequestFinishedListener(requestFinishedListener) 559 .build() 560 .start(); 561 callback.blockForDone(); 562 requestFinishedListener.blockUntilDone(); 563 Date endTime = new Date(); 564 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 565 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 566 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); 567 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 568 // Check that annotation got updated in onSucceeded() callback. 569 assertThat(requestInfo.getAnnotations()).containsExactly(requestAnnotation); 570 assertThat(requestAnnotation.get()).isTrue(); 571 } 572 573 @Test 574 @SmallTest 575 // Tests a failed request where the error originates from Java. testOrderFailedRequestJava()576 public void testOrderFailedRequestJava() throws Exception { 577 final TestUrlRequestCallback callback = 578 new TestUrlRequestCallback() { 579 @Override 580 public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { 581 throw new RuntimeException("make this request fail"); 582 } 583 }; 584 TestRequestFinishedListener requestFinishedListener = 585 new AssertCallbackDoneRequestFinishedListener(callback); 586 mTestRule 587 .getTestFramework() 588 .getEngine() 589 .addRequestFinishedListener(requestFinishedListener); 590 UrlRequest.Builder urlRequestBuilder = 591 mTestRule 592 .getTestFramework() 593 .getEngine() 594 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 595 urlRequestBuilder.build().start(); 596 callback.blockForDone(); 597 assertThat(callback.mOnErrorCalled).isTrue(); 598 requestFinishedListener.blockUntilDone(); 599 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 600 assertWithMessage("RequestFinishedInfo.Listener must be called") 601 .that(requestInfo) 602 .isNotNull(); 603 assertThat(requestInfo.getUrl()).isEqualTo(mUrl); 604 assertThat(requestInfo.getAnnotations()).isEmpty(); 605 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.FAILED); 606 assertThat(requestInfo.getException()) 607 .hasMessageThat() 608 .isEqualTo("Exception received from UrlRequest.Callback"); 609 RequestFinishedInfo.Metrics metrics = requestInfo.getMetrics(); 610 assertWithMessage("RequestFinishedInfo.getMetrics() must not be null") 611 .that(metrics) 612 .isNotNull(); 613 } 614 615 @Test 616 @SmallTest 617 // Tests a failed request where the error originates from native code. testOrderFailedRequestNative()618 public void testOrderFailedRequestNative() throws Exception { 619 String connectionRefusedUrl = "http://127.0.0.1:3"; 620 final TestUrlRequestCallback callback = new TestUrlRequestCallback(); 621 TestRequestFinishedListener requestFinishedListener = 622 new AssertCallbackDoneRequestFinishedListener(callback); 623 mTestRule 624 .getTestFramework() 625 .getEngine() 626 .addRequestFinishedListener(requestFinishedListener); 627 UrlRequest.Builder urlRequestBuilder = 628 mTestRule 629 .getTestFramework() 630 .getEngine() 631 .newUrlRequestBuilder( 632 connectionRefusedUrl, callback, callback.getExecutor()); 633 urlRequestBuilder.build().start(); 634 callback.blockForDone(); 635 assertThat(callback.mOnErrorCalled).isTrue(); 636 requestFinishedListener.blockUntilDone(); 637 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 638 assertWithMessage("RequestFinishedInfo.Listener must be called") 639 .that(requestInfo) 640 .isNotNull(); 641 assertThat(requestInfo.getUrl()).isEqualTo(connectionRefusedUrl); 642 assertThat(requestInfo.getAnnotations()).isEmpty(); 643 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.FAILED); 644 assertThat(requestInfo.getException()).isNotNull(); 645 assertThat(((NetworkException) requestInfo.getException()).getErrorCode()) 646 .isEqualTo(NetworkException.ERROR_CONNECTION_REFUSED); 647 RequestFinishedInfo.Metrics metrics = requestInfo.getMetrics(); 648 assertWithMessage("RequestFinishedInfo.getMetrics() must not be null") 649 .that(metrics) 650 .isNotNull(); 651 } 652 653 @Test 654 @SmallTest testOrderCanceledRequest()655 public void testOrderCanceledRequest() throws Exception { 656 final TestUrlRequestCallback callback = 657 new TestUrlRequestCallback() { 658 @Override 659 public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { 660 super.onResponseStarted(request, info); 661 request.cancel(); 662 } 663 }; 664 665 TestRequestFinishedListener requestFinishedListener = 666 new AssertCallbackDoneRequestFinishedListener(callback); 667 mTestRule 668 .getTestFramework() 669 .getEngine() 670 .addRequestFinishedListener(requestFinishedListener); 671 ExperimentalUrlRequest.Builder urlRequestBuilder = 672 mTestRule 673 .getTestFramework() 674 .getEngine() 675 .newUrlRequestBuilder(mUrl, callback, callback.getExecutor()); 676 Date startTime = new Date(); 677 urlRequestBuilder 678 .addRequestAnnotation("request annotation") 679 .addRequestAnnotation(this) 680 .build() 681 .start(); 682 callback.blockForDone(); 683 requestFinishedListener.blockUntilDone(); 684 Date endTime = new Date(); 685 686 RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); 687 MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); 688 assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.CANCELED); 689 MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); 690 691 assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); 692 } 693 } 694