Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 package org.chromium.net; | 5 package org.chromium.net; | 
| 6 | 6 | 
| 7 import android.os.ConditionVariable; | 7 import android.os.ConditionVariable; | 
| 8 import android.os.StrictMode; | 8 import android.os.StrictMode; | 
| 9 | 9 | 
| 10 import static junit.framework.Assert.assertEquals; | 10 import static junit.framework.Assert.assertEquals; | 
| 11 import static junit.framework.Assert.assertFalse; | 11 import static junit.framework.Assert.assertFalse; | 
| 12 import static junit.framework.Assert.assertNotNull; | 12 import static junit.framework.Assert.assertNotNull; | 
| 13 import static junit.framework.Assert.assertNull; | 13 import static junit.framework.Assert.assertNull; | 
| 14 import static junit.framework.Assert.assertTrue; | 14 import static junit.framework.Assert.assertTrue; | 
| 15 | 15 | 
| 16 import java.nio.ByteBuffer; | 16 import java.nio.ByteBuffer; | 
| 17 import java.util.ArrayList; | 17 import java.util.ArrayList; | 
| 18 import java.util.concurrent.Executor; | 18 import java.util.concurrent.Executor; | 
| 19 import java.util.concurrent.ExecutorService; | 19 import java.util.concurrent.ExecutorService; | 
| 20 import java.util.concurrent.Executors; | 20 import java.util.concurrent.Executors; | 
| 21 import java.util.concurrent.ThreadFactory; | 21 import java.util.concurrent.ThreadFactory; | 
| 22 import java.util.concurrent.TimeUnit; | |
| 22 | 23 | 
| 23 /** | 24 /** | 
| 24 * Callback that tracks information from different callbacks and and has a | 25 * Callback that tracks information from different callbacks and and has a | 
| 25 * method to block thread until the request completes on another thread. | 26 * method to block thread until the request completes on another thread. | 
| 26 * Allows to cancel, block request or throw an exception from an arbitrary step. | 27 * Allows to cancel, block request or throw an exception from an arbitrary step. | 
| 27 */ | 28 */ | 
| 28 class TestUrlRequestCallback extends UrlRequest.Callback { | 29 class TestUrlRequestCallback extends UrlRequest.Callback { | 
| 29 public ArrayList<UrlResponseInfo> mRedirectResponseInfoList = new ArrayList< UrlResponseInfo>(); | 30 public ArrayList<UrlResponseInfo> mRedirectResponseInfoList = new ArrayList< UrlResponseInfo>(); | 
| 30 public ArrayList<String> mRedirectUrlList = new ArrayList<String>(); | 31 public ArrayList<String> mRedirectUrlList = new ArrayList<String>(); | 
| 31 public UrlResponseInfo mResponseInfo; | 32 public UrlResponseInfo mResponseInfo; | 
| 32 public UrlRequestException mError; | 33 public UrlRequestException mError; | 
| 33 | 34 | 
| 34 public ResponseStep mResponseStep = ResponseStep.NOTHING; | 35 public ResponseStep mResponseStep = ResponseStep.NOTHING; | 
| 35 | 36 | 
| 36 public int mRedirectCount = 0; | 37 public int mRedirectCount = 0; | 
| 37 public boolean mOnErrorCalled = false; | 38 public boolean mOnErrorCalled = false; | 
| 38 public boolean mOnCanceledCalled = false; | 39 public boolean mOnCanceledCalled = false; | 
| 39 | 40 | 
| 40 public int mHttpResponseDataLength = 0; | 41 public int mHttpResponseDataLength = 0; | 
| 41 public String mResponseAsString = ""; | 42 public String mResponseAsString = ""; | 
| 42 | 43 | 
| 43 private static final int READ_BUFFER_SIZE = 32 * 1024; | 44 private static final int READ_BUFFER_SIZE = 32 * 1024; | 
| 44 | 45 | 
| 45 // When false, the consumer is responsible for all calls into the request | 46 // When false, the consumer is responsible for all calls into the request | 
| 46 // that advance it. | 47 // that advance it. | 
| 47 private boolean mAutoAdvance = true; | 48 private boolean mAutoAdvance = true; | 
| 49 // Whether an exception is thrown by maybeThrowCancelOrPause(). | |
| 50 private boolean mListenerExceptionThrown; | |
| 48 | 51 | 
| 49 // Conditionally fail on certain steps. | 52 // Conditionally fail on certain steps. | 
| 50 private FailureType mFailureType = FailureType.NONE; | 53 private FailureType mFailureType = FailureType.NONE; | 
| 51 private ResponseStep mFailureStep = ResponseStep.NOTHING; | 54 private ResponseStep mFailureStep = ResponseStep.NOTHING; | 
| 52 | 55 | 
| 53 // Signals when request is done either successfully or not. | 56 // Signals when request is done either successfully or not. | 
| 54 private final ConditionVariable mDone = new ConditionVariable(); | 57 private final ConditionVariable mDone = new ConditionVariable(); | 
| 55 | 58 | 
| 56 // Signaled on each step when mAutoAdvance is false. | 59 // Signaled on each step when mAutoAdvance is false. | 
| 57 private final ConditionVariable mStepBlock = new ConditionVariable(); | 60 private final ConditionVariable mStepBlock = new ConditionVariable(); | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 84 }); | 87 }); | 
| 85 return mExecutorThread; | 88 return mExecutorThread; | 
| 86 } | 89 } | 
| 87 } | 90 } | 
| 88 | 91 | 
| 89 public enum ResponseStep { | 92 public enum ResponseStep { | 
| 90 NOTHING, | 93 NOTHING, | 
| 91 ON_RECEIVED_REDIRECT, | 94 ON_RECEIVED_REDIRECT, | 
| 92 ON_RESPONSE_STARTED, | 95 ON_RESPONSE_STARTED, | 
| 93 ON_READ_COMPLETED, | 96 ON_READ_COMPLETED, | 
| 94 ON_SUCCEEDED | 97 ON_SUCCEEDED, | 
| 98 ON_FAILED, | |
| 99 ON_CANCELED, | |
| 95 } | 100 } | 
| 96 | 101 | 
| 97 public enum FailureType { | 102 public enum FailureType { | 
| 98 NONE, | 103 NONE, | 
| 99 CANCEL_SYNC, | 104 CANCEL_SYNC, | 
| 100 CANCEL_ASYNC, | 105 CANCEL_ASYNC, | 
| 101 // Same as above, but continues to advance the request after posting | 106 // Same as above, but continues to advance the request after posting | 
| 102 // the cancellation task. | 107 // the cancellation task. | 
| 103 CANCEL_ASYNC_WITHOUT_PAUSE, | 108 CANCEL_ASYNC_WITHOUT_PAUSE, | 
| 104 THROW_SYNC | 109 THROW_SYNC | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 123 } | 128 } | 
| 124 | 129 | 
| 125 public Executor getExecutor() { | 130 public Executor getExecutor() { | 
| 126 return mExecutorService; | 131 return mExecutorService; | 
| 127 } | 132 } | 
| 128 | 133 | 
| 129 public void shutdownExecutor() { | 134 public void shutdownExecutor() { | 
| 130 mExecutorService.shutdown(); | 135 mExecutorService.shutdown(); | 
| 131 } | 136 } | 
| 132 | 137 | 
| 138 /** | |
| 139 * Shuts down the ExecutorService and waits until it executes all posted | |
| 140 * tasks. | |
| 141 */ | |
| 142 public void shutdownExecutorAndWait() { | |
| 143 mExecutorService.shutdown(); | |
| 144 try { | |
| 145 // Termination shouldn't take long. Use 5 min which should be more t han enough. | |
| 146 mExecutorService.awaitTermination(5, TimeUnit.MINUTES); | |
| 
 
kapishnikov
2016/08/31 20:35:15
Nit: Also, can we make the waiting interval smalle
 
xunjieli
2016/08/31 20:44:46
Done.
 
 | |
| 147 } catch (InterruptedException e) { | |
| 148 assertTrue(false); | |
| 
 
kapishnikov
2016/08/31 20:13:20
It would be good to add a message to the assert. E
 
xunjieli
2016/08/31 20:44:46
Done.
 
 | |
| 149 } | |
| 150 assertTrue(mExecutorService.isTerminated()); | |
| 151 } | |
| 152 | |
| 133 @Override | 153 @Override | 
| 134 public void onRedirectReceived( | 154 public void onRedirectReceived( | 
| 135 UrlRequest request, UrlResponseInfo info, String newLocationUrl) { | 155 UrlRequest request, UrlResponseInfo info, String newLocationUrl) { | 
| 136 assertEquals(mExecutorThread, Thread.currentThread()); | 156 assertEquals(mExecutorThread, Thread.currentThread()); | 
| 137 assertFalse(request.isDone()); | 157 assertFalse(request.isDone()); | 
| 138 assertTrue(mResponseStep == ResponseStep.NOTHING | 158 assertTrue(mResponseStep == ResponseStep.NOTHING | 
| 139 || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT); | 159 || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT); | 
| 140 assertNull(mError); | 160 assertNull(mError); | 
| 141 | 161 | 
| 142 mResponseStep = ResponseStep.ON_RECEIVED_REDIRECT; | 162 mResponseStep = ResponseStep.ON_RECEIVED_REDIRECT; | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 @Override | 231 @Override | 
| 212 public void onFailed(UrlRequest request, UrlResponseInfo info, UrlRequestExc eption error) { | 232 public void onFailed(UrlRequest request, UrlResponseInfo info, UrlRequestExc eption error) { | 
| 213 assertEquals(mExecutorThread, Thread.currentThread()); | 233 assertEquals(mExecutorThread, Thread.currentThread()); | 
| 214 assertTrue(request.isDone()); | 234 assertTrue(request.isDone()); | 
| 215 // Shouldn't happen after success. | 235 // Shouldn't happen after success. | 
| 216 assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED); | 236 assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED); | 
| 217 // Should happen at most once for a single request. | 237 // Should happen at most once for a single request. | 
| 218 assertFalse(mOnErrorCalled); | 238 assertFalse(mOnErrorCalled); | 
| 219 assertFalse(mOnCanceledCalled); | 239 assertFalse(mOnCanceledCalled); | 
| 220 assertNull(mError); | 240 assertNull(mError); | 
| 221 if (mFailureType == FailureType.THROW_SYNC) { | 241 if (mListenerExceptionThrown) { | 
| 222 assertEquals(UrlRequestError.LISTENER_EXCEPTION_THROWN, error.getErr orCode()); | 242 assertEquals(UrlRequestError.LISTENER_EXCEPTION_THROWN, error.getErr orCode()); | 
| 223 assertEquals(0, error.getCronetInternalErrorCode()); | 243 assertEquals(0, error.getCronetInternalErrorCode()); | 
| 224 assertEquals("Exception received from UrlRequest.Callback", error.ge tMessage()); | 244 assertEquals("Exception received from UrlRequest.Callback", error.ge tMessage()); | 
| 225 assertNotNull(error.getCause()); | 245 assertNotNull(error.getCause()); | 
| 226 assertTrue(error.getCause() instanceof IllegalStateException); | 246 assertTrue(error.getCause() instanceof IllegalStateException); | 
| 227 assertEquals("Listener Exception.", error.getCause().getMessage()); | 247 assertEquals("Listener Exception.", error.getCause().getMessage()); | 
| 228 assertFalse(error.immediatelyRetryable()); | 248 assertFalse(error.immediatelyRetryable()); | 
| 229 } | 249 } | 
| 230 | 250 | 
| 251 mResponseStep = ResponseStep.ON_FAILED; | |
| 231 mOnErrorCalled = true; | 252 mOnErrorCalled = true; | 
| 232 mError = error; | 253 mError = error; | 
| 233 openDone(); | 254 openDone(); | 
| 234 maybeThrowCancelOrPause(request); | 255 maybeThrowCancelOrPause(request); | 
| 235 } | 256 } | 
| 236 | 257 | 
| 237 @Override | 258 @Override | 
| 238 public void onCanceled(UrlRequest request, UrlResponseInfo info) { | 259 public void onCanceled(UrlRequest request, UrlResponseInfo info) { | 
| 239 assertEquals(mExecutorThread, Thread.currentThread()); | 260 assertEquals(mExecutorThread, Thread.currentThread()); | 
| 240 assertTrue(request.isDone()); | 261 assertTrue(request.isDone()); | 
| 241 // Should happen at most once for a single request. | 262 // Should happen at most once for a single request. | 
| 242 assertFalse(mOnCanceledCalled); | 263 assertFalse(mOnCanceledCalled); | 
| 243 assertFalse(mOnErrorCalled); | 264 assertFalse(mOnErrorCalled); | 
| 244 assertNull(mError); | 265 assertNull(mError); | 
| 245 | 266 | 
| 267 mResponseStep = ResponseStep.ON_CANCELED; | |
| 246 mOnCanceledCalled = true; | 268 mOnCanceledCalled = true; | 
| 247 openDone(); | 269 openDone(); | 
| 248 maybeThrowCancelOrPause(request); | 270 maybeThrowCancelOrPause(request); | 
| 249 } | 271 } | 
| 250 | 272 | 
| 251 public void startNextRead(UrlRequest request) { | 273 public void startNextRead(UrlRequest request) { | 
| 252 startNextRead(request, ByteBuffer.allocateDirect(READ_BUFFER_SIZE)); | 274 startNextRead(request, ByteBuffer.allocateDirect(READ_BUFFER_SIZE)); | 
| 253 } | 275 } | 
| 254 | 276 | 
| 255 public void startNextRead(UrlRequest request, ByteBuffer buffer) { | 277 public void startNextRead(UrlRequest request, ByteBuffer buffer) { | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 266 | 288 | 
| 267 protected void openDone() { | 289 protected void openDone() { | 
| 268 mDone.open(); | 290 mDone.open(); | 
| 269 } | 291 } | 
| 270 | 292 | 
| 271 /** | 293 /** | 
| 272 * Returns {@code false} if the listener should continue to advance the | 294 * Returns {@code false} if the listener should continue to advance the | 
| 273 * request. | 295 * request. | 
| 274 */ | 296 */ | 
| 275 private boolean maybeThrowCancelOrPause(final UrlRequest request) { | 297 private boolean maybeThrowCancelOrPause(final UrlRequest request) { | 
| 298 assertEquals(mExecutorThread, Thread.currentThread()); | |
| 276 if (mResponseStep != mFailureStep || mFailureType == FailureType.NONE) { | 299 if (mResponseStep != mFailureStep || mFailureType == FailureType.NONE) { | 
| 277 if (!mAutoAdvance) { | 300 if (!mAutoAdvance) { | 
| 278 mStepBlock.open(); | 301 mStepBlock.open(); | 
| 279 return true; | 302 return true; | 
| 280 } | 303 } | 
| 281 return false; | 304 return false; | 
| 282 } | 305 } | 
| 283 | 306 | 
| 284 if (mFailureType == FailureType.THROW_SYNC) { | 307 if (mFailureType == FailureType.THROW_SYNC) { | 
| 308 assertFalse(mListenerExceptionThrown); | |
| 309 mListenerExceptionThrown = true; | |
| 285 throw new IllegalStateException("Listener Exception."); | 310 throw new IllegalStateException("Listener Exception."); | 
| 286 } | 311 } | 
| 287 Runnable task = new Runnable() { | 312 Runnable task = new Runnable() { | 
| 288 public void run() { | 313 public void run() { | 
| 289 request.cancel(); | 314 request.cancel(); | 
| 290 } | 315 } | 
| 291 }; | 316 }; | 
| 292 if (mFailureType == FailureType.CANCEL_ASYNC | 317 if (mFailureType == FailureType.CANCEL_ASYNC | 
| 293 || mFailureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE) { | 318 || mFailureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE) { | 
| 294 getExecutor().execute(task); | 319 getExecutor().execute(task); | 
| 295 } else { | 320 } else { | 
| 296 task.run(); | 321 task.run(); | 
| 297 } | 322 } | 
| 298 return mFailureType != FailureType.CANCEL_ASYNC_WITHOUT_PAUSE; | 323 return mFailureType != FailureType.CANCEL_ASYNC_WITHOUT_PAUSE; | 
| 299 } | 324 } | 
| 300 } | 325 } | 
| OLD | NEW |