| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.net; | 5 package org.chromium.net; |
| 6 | 6 |
| 7 import android.os.ConditionVariable; | 7 import android.os.ConditionVariable; |
| 8 | 8 |
| 9 import static junit.framework.Assert.assertEquals; | 9 import static junit.framework.Assert.assertEquals; |
| 10 import static junit.framework.Assert.assertFalse; | 10 import static junit.framework.Assert.assertFalse; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 | 62 |
| 63 // position() of ByteBuffer prior to read() call. | 63 // position() of ByteBuffer prior to read() call. |
| 64 private int mBufferPositionBeforeRead; | 64 private int mBufferPositionBeforeRead; |
| 65 | 65 |
| 66 // Data to write. | 66 // Data to write. |
| 67 private final ArrayList<WriteBuffer> mWriteBuffers = new ArrayList<WriteBuff
er>(); | 67 private final ArrayList<WriteBuffer> mWriteBuffers = new ArrayList<WriteBuff
er>(); |
| 68 | 68 |
| 69 // Buffers that we yet to receive the corresponding onWriteCompleted callbac
k. | 69 // Buffers that we yet to receive the corresponding onWriteCompleted callbac
k. |
| 70 private final ArrayList<WriteBuffer> mWriteBuffersToBeAcked = new ArrayList<
WriteBuffer>(); | 70 private final ArrayList<WriteBuffer> mWriteBuffersToBeAcked = new ArrayList<
WriteBuffer>(); |
| 71 | 71 |
| 72 // Whether to use a direct executor. |
| 73 private final boolean mUseDirectExecutor; |
| 74 private final DirectExecutor mDirectExecutor; |
| 75 |
| 72 private class ExecutorThreadFactory implements ThreadFactory { | 76 private class ExecutorThreadFactory implements ThreadFactory { |
| 73 public Thread newThread(Runnable r) { | 77 public Thread newThread(Runnable r) { |
| 74 mExecutorThread = new Thread(r); | 78 mExecutorThread = new Thread(r); |
| 75 return mExecutorThread; | 79 return mExecutorThread; |
| 76 } | 80 } |
| 77 } | 81 } |
| 78 | 82 |
| 79 private static class WriteBuffer { | 83 private static class WriteBuffer { |
| 80 final ByteBuffer mBuffer; | 84 final ByteBuffer mBuffer; |
| 81 final boolean mFlush; | 85 final boolean mFlush; |
| 82 public WriteBuffer(ByteBuffer buffer, boolean flush) { | 86 public WriteBuffer(ByteBuffer buffer, boolean flush) { |
| 83 mBuffer = buffer; | 87 mBuffer = buffer; |
| 84 mFlush = flush; | 88 mFlush = flush; |
| 85 } | 89 } |
| 86 } | 90 } |
| 87 | 91 |
| 92 private static class DirectExecutor implements Executor { |
| 93 @Override |
| 94 public void execute(Runnable task) { |
| 95 task.run(); |
| 96 } |
| 97 } |
| 98 |
| 88 public enum ResponseStep { | 99 public enum ResponseStep { |
| 89 NOTHING, | 100 NOTHING, |
| 90 ON_STREAM_READY, | 101 ON_STREAM_READY, |
| 91 ON_RESPONSE_STARTED, | 102 ON_RESPONSE_STARTED, |
| 92 ON_READ_COMPLETED, | 103 ON_READ_COMPLETED, |
| 93 ON_WRITE_COMPLETED, | 104 ON_WRITE_COMPLETED, |
| 94 ON_TRAILERS, | 105 ON_TRAILERS, |
| 95 ON_CANCELED, | 106 ON_CANCELED, |
| 96 ON_FAILED, | 107 ON_FAILED, |
| 97 ON_SUCCEEDED, | 108 ON_SUCCEEDED, |
| 98 } | 109 } |
| 99 | 110 |
| 100 public enum FailureType { | 111 public enum FailureType { |
| 101 NONE, | 112 NONE, |
| 102 CANCEL_SYNC, | 113 CANCEL_SYNC, |
| 103 CANCEL_ASYNC, | 114 CANCEL_ASYNC, |
| 104 // Same as above, but continues to advance the stream after posting | 115 // Same as above, but continues to advance the stream after posting |
| 105 // the cancellation task. | 116 // the cancellation task. |
| 106 CANCEL_ASYNC_WITHOUT_PAUSE, | 117 CANCEL_ASYNC_WITHOUT_PAUSE, |
| 107 THROW_SYNC | 118 THROW_SYNC |
| 108 } | 119 } |
| 109 | 120 |
| 121 public TestBidirectionalStreamCallback() { |
| 122 mUseDirectExecutor = false; |
| 123 mDirectExecutor = null; |
| 124 } |
| 125 |
| 126 public TestBidirectionalStreamCallback(boolean useDirectExecutor) { |
| 127 mUseDirectExecutor = useDirectExecutor; |
| 128 mDirectExecutor = new DirectExecutor(); |
| 129 } |
| 130 |
| 110 public void setAutoAdvance(boolean autoAdvance) { | 131 public void setAutoAdvance(boolean autoAdvance) { |
| 111 mAutoAdvance = autoAdvance; | 132 mAutoAdvance = autoAdvance; |
| 112 } | 133 } |
| 113 | 134 |
| 114 public void setFailure(FailureType failureType, ResponseStep failureStep) { | 135 public void setFailure(FailureType failureType, ResponseStep failureStep) { |
| 115 mFailureStep = failureStep; | 136 mFailureStep = failureStep; |
| 116 mFailureType = failureType; | 137 mFailureType = failureType; |
| 117 } | 138 } |
| 118 | 139 |
| 119 public void blockForDone() { | 140 public void blockForDone() { |
| 120 mDone.block(); | 141 mDone.block(); |
| 121 } | 142 } |
| 122 | 143 |
| 123 public void waitForNextReadStep() { | 144 public void waitForNextReadStep() { |
| 124 mReadStepBlock.block(); | 145 mReadStepBlock.block(); |
| 125 mReadStepBlock.close(); | 146 mReadStepBlock.close(); |
| 126 } | 147 } |
| 127 | 148 |
| 128 public void waitForNextWriteStep() { | 149 public void waitForNextWriteStep() { |
| 129 mWriteStepBlock.block(); | 150 mWriteStepBlock.block(); |
| 130 mWriteStepBlock.close(); | 151 mWriteStepBlock.close(); |
| 131 } | 152 } |
| 132 | 153 |
| 133 public Executor getExecutor() { | 154 public Executor getExecutor() { |
| 155 if (mUseDirectExecutor) { |
| 156 return mDirectExecutor; |
| 157 } |
| 134 return mExecutorService; | 158 return mExecutorService; |
| 135 } | 159 } |
| 136 | 160 |
| 137 public void shutdownExecutor() { | 161 public void shutdownExecutor() { |
| 162 if (mUseDirectExecutor) { |
| 163 throw new UnsupportedOperationException("DirectExecutor doesn't supp
ort shutdown"); |
| 164 } |
| 138 mExecutorService.shutdown(); | 165 mExecutorService.shutdown(); |
| 139 } | 166 } |
| 140 | 167 |
| 141 public void addWriteData(byte[] data) { | 168 public void addWriteData(byte[] data) { |
| 142 addWriteData(data, true); | 169 addWriteData(data, true); |
| 143 } | 170 } |
| 144 | 171 |
| 145 public void addWriteData(byte[] data, boolean flush) { | 172 public void addWriteData(byte[] data, boolean flush) { |
| 146 ByteBuffer writeBuffer = ByteBuffer.allocateDirect(data.length); | 173 ByteBuffer writeBuffer = ByteBuffer.allocateDirect(data.length); |
| 147 writeBuffer.put(data); | 174 writeBuffer.put(data); |
| 148 writeBuffer.flip(); | 175 writeBuffer.flip(); |
| 149 mWriteBuffers.add(new WriteBuffer(writeBuffer, flush)); | 176 mWriteBuffers.add(new WriteBuffer(writeBuffer, flush)); |
| 150 mWriteBuffersToBeAcked.add(new WriteBuffer(writeBuffer, flush)); | 177 mWriteBuffersToBeAcked.add(new WriteBuffer(writeBuffer, flush)); |
| 151 } | 178 } |
| 152 | 179 |
| 153 @Override | 180 @Override |
| 154 public void onStreamReady(BidirectionalStream stream) { | 181 public void onStreamReady(BidirectionalStream stream) { |
| 155 assertEquals(mExecutorThread, Thread.currentThread()); | 182 checkOnValidThread(); |
| 156 assertFalse(stream.isDone()); | 183 assertFalse(stream.isDone()); |
| 157 assertEquals(ResponseStep.NOTHING, mResponseStep); | 184 assertEquals(ResponseStep.NOTHING, mResponseStep); |
| 158 assertNull(mError); | 185 assertNull(mError); |
| 159 mResponseStep = ResponseStep.ON_STREAM_READY; | 186 mResponseStep = ResponseStep.ON_STREAM_READY; |
| 160 if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) { | 187 if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) { |
| 161 return; | 188 return; |
| 162 } | 189 } |
| 163 startNextWrite(stream); | 190 startNextWrite(stream); |
| 164 } | 191 } |
| 165 | 192 |
| 166 @Override | 193 @Override |
| 167 public void onResponseHeadersReceived(BidirectionalStream stream, UrlRespons
eInfo info) { | 194 public void onResponseHeadersReceived(BidirectionalStream stream, UrlRespons
eInfo info) { |
| 168 assertEquals(mExecutorThread, Thread.currentThread()); | 195 checkOnValidThread(); |
| 169 assertFalse(stream.isDone()); | 196 assertFalse(stream.isDone()); |
| 170 assertTrue(mResponseStep == ResponseStep.NOTHING | 197 assertTrue(mResponseStep == ResponseStep.NOTHING |
| 171 || mResponseStep == ResponseStep.ON_STREAM_READY | 198 || mResponseStep == ResponseStep.ON_STREAM_READY |
| 172 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED); | 199 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED); |
| 173 assertNull(mError); | 200 assertNull(mError); |
| 174 | 201 |
| 175 mResponseStep = ResponseStep.ON_RESPONSE_STARTED; | 202 mResponseStep = ResponseStep.ON_RESPONSE_STARTED; |
| 176 mResponseInfo = info; | 203 mResponseInfo = info; |
| 177 if (maybeThrowCancelOrPause(stream, mReadStepBlock)) { | 204 if (maybeThrowCancelOrPause(stream, mReadStepBlock)) { |
| 178 return; | 205 return; |
| 179 } | 206 } |
| 180 startNextRead(stream); | 207 startNextRead(stream); |
| 181 } | 208 } |
| 182 | 209 |
| 183 @Override | 210 @Override |
| 184 public void onReadCompleted(BidirectionalStream stream, UrlResponseInfo info
, | 211 public void onReadCompleted(BidirectionalStream stream, UrlResponseInfo info
, |
| 185 ByteBuffer byteBuffer, boolean endOfStream) { | 212 ByteBuffer byteBuffer, boolean endOfStream) { |
| 186 assertEquals(mExecutorThread, Thread.currentThread()); | 213 checkOnValidThread(); |
| 187 assertFalse(stream.isDone()); | 214 assertFalse(stream.isDone()); |
| 188 assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED | 215 assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED |
| 189 || mResponseStep == ResponseStep.ON_READ_COMPLETED | 216 || mResponseStep == ResponseStep.ON_READ_COMPLETED |
| 190 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED | 217 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED |
| 191 || mResponseStep == ResponseStep.ON_TRAILERS); | 218 || mResponseStep == ResponseStep.ON_TRAILERS); |
| 192 assertNull(mError); | 219 assertNull(mError); |
| 193 | 220 |
| 194 mResponseStep = ResponseStep.ON_READ_COMPLETED; | 221 mResponseStep = ResponseStep.ON_READ_COMPLETED; |
| 195 mResponseInfo = info; | 222 mResponseInfo = info; |
| 196 | 223 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 210 } | 237 } |
| 211 // Do not read if EOF has been reached. | 238 // Do not read if EOF has been reached. |
| 212 if (!endOfStream) { | 239 if (!endOfStream) { |
| 213 startNextRead(stream); | 240 startNextRead(stream); |
| 214 } | 241 } |
| 215 } | 242 } |
| 216 | 243 |
| 217 @Override | 244 @Override |
| 218 public void onWriteCompleted(BidirectionalStream stream, UrlResponseInfo inf
o, | 245 public void onWriteCompleted(BidirectionalStream stream, UrlResponseInfo inf
o, |
| 219 ByteBuffer buffer, boolean endOfStream) { | 246 ByteBuffer buffer, boolean endOfStream) { |
| 220 assertEquals(mExecutorThread, Thread.currentThread()); | 247 checkOnValidThread(); |
| 221 assertFalse(stream.isDone()); | 248 assertFalse(stream.isDone()); |
| 222 assertNull(mError); | 249 assertNull(mError); |
| 223 mResponseStep = ResponseStep.ON_WRITE_COMPLETED; | 250 mResponseStep = ResponseStep.ON_WRITE_COMPLETED; |
| 224 mResponseInfo = info; | 251 mResponseInfo = info; |
| 225 if (!mWriteBuffersToBeAcked.isEmpty()) { | 252 if (!mWriteBuffersToBeAcked.isEmpty()) { |
| 226 assertEquals(buffer, mWriteBuffersToBeAcked.get(0).mBuffer); | 253 assertEquals(buffer, mWriteBuffersToBeAcked.get(0).mBuffer); |
| 227 mWriteBuffersToBeAcked.remove(0); | 254 mWriteBuffersToBeAcked.remove(0); |
| 228 } | 255 } |
| 229 if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) { | 256 if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) { |
| 230 return; | 257 return; |
| 231 } | 258 } |
| 232 startNextWrite(stream); | 259 startNextWrite(stream); |
| 233 } | 260 } |
| 234 | 261 |
| 235 @Override | 262 @Override |
| 236 public void onResponseTrailersReceived(BidirectionalStream stream, UrlRespon
seInfo info, | 263 public void onResponseTrailersReceived(BidirectionalStream stream, UrlRespon
seInfo info, |
| 237 UrlResponseInfo.HeaderBlock trailers) { | 264 UrlResponseInfo.HeaderBlock trailers) { |
| 238 assertEquals(mExecutorThread, Thread.currentThread()); | 265 checkOnValidThread(); |
| 239 assertFalse(stream.isDone()); | 266 assertFalse(stream.isDone()); |
| 240 assertNull(mError); | 267 assertNull(mError); |
| 241 mResponseStep = ResponseStep.ON_TRAILERS; | 268 mResponseStep = ResponseStep.ON_TRAILERS; |
| 242 mResponseInfo = info; | 269 mResponseInfo = info; |
| 243 mTrailers = trailers; | 270 mTrailers = trailers; |
| 244 if (maybeThrowCancelOrPause(stream, mReadStepBlock)) { | 271 if (maybeThrowCancelOrPause(stream, mReadStepBlock)) { |
| 245 return; | 272 return; |
| 246 } | 273 } |
| 247 } | 274 } |
| 248 | 275 |
| 249 @Override | 276 @Override |
| 250 public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info) { | 277 public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info) { |
| 251 assertEquals(mExecutorThread, Thread.currentThread()); | 278 checkOnValidThread(); |
| 252 assertTrue(stream.isDone()); | 279 assertTrue(stream.isDone()); |
| 253 assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED | 280 assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED |
| 254 || mResponseStep == ResponseStep.ON_READ_COMPLETED | 281 || mResponseStep == ResponseStep.ON_READ_COMPLETED |
| 255 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED | 282 || mResponseStep == ResponseStep.ON_WRITE_COMPLETED |
| 256 || mResponseStep == ResponseStep.ON_TRAILERS); | 283 || mResponseStep == ResponseStep.ON_TRAILERS); |
| 257 assertFalse(mOnErrorCalled); | 284 assertFalse(mOnErrorCalled); |
| 258 assertFalse(mOnCanceledCalled); | 285 assertFalse(mOnCanceledCalled); |
| 259 assertNull(mError); | 286 assertNull(mError); |
| 260 assertEquals(0, mWriteBuffers.size()); | 287 assertEquals(0, mWriteBuffers.size()); |
| 261 assertEquals(0, mWriteBuffersToBeAcked.size()); | 288 assertEquals(0, mWriteBuffersToBeAcked.size()); |
| 262 | 289 |
| 263 mResponseStep = ResponseStep.ON_SUCCEEDED; | 290 mResponseStep = ResponseStep.ON_SUCCEEDED; |
| 264 mResponseInfo = info; | 291 mResponseInfo = info; |
| 265 openDone(); | 292 openDone(); |
| 266 maybeThrowCancelOrPause(stream, mReadStepBlock); | 293 maybeThrowCancelOrPause(stream, mReadStepBlock); |
| 267 } | 294 } |
| 268 | 295 |
| 269 @Override | 296 @Override |
| 270 public void onFailed(BidirectionalStream stream, UrlResponseInfo info, Crone
tException error) { | 297 public void onFailed(BidirectionalStream stream, UrlResponseInfo info, Crone
tException error) { |
| 271 assertEquals(mExecutorThread, Thread.currentThread()); | 298 checkOnValidThread(); |
| 272 assertTrue(stream.isDone()); | 299 assertTrue(stream.isDone()); |
| 273 // Shouldn't happen after success. | 300 // Shouldn't happen after success. |
| 274 assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED); | 301 assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED); |
| 275 // Should happen at most once for a single stream. | 302 // Should happen at most once for a single stream. |
| 276 assertFalse(mOnErrorCalled); | 303 assertFalse(mOnErrorCalled); |
| 277 assertFalse(mOnCanceledCalled); | 304 assertFalse(mOnCanceledCalled); |
| 278 assertNull(mError); | 305 assertNull(mError); |
| 279 mResponseStep = ResponseStep.ON_FAILED; | 306 mResponseStep = ResponseStep.ON_FAILED; |
| 280 mResponseInfo = info; | 307 mResponseInfo = info; |
| 281 | 308 |
| 282 mOnErrorCalled = true; | 309 mOnErrorCalled = true; |
| 283 mError = error; | 310 mError = error; |
| 284 openDone(); | 311 openDone(); |
| 285 maybeThrowCancelOrPause(stream, mReadStepBlock); | 312 maybeThrowCancelOrPause(stream, mReadStepBlock); |
| 286 } | 313 } |
| 287 | 314 |
| 288 @Override | 315 @Override |
| 289 public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) { | 316 public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) { |
| 290 assertEquals(mExecutorThread, Thread.currentThread()); | 317 checkOnValidThread(); |
| 291 assertTrue(stream.isDone()); | 318 assertTrue(stream.isDone()); |
| 292 // Should happen at most once for a single stream. | 319 // Should happen at most once for a single stream. |
| 293 assertFalse(mOnCanceledCalled); | 320 assertFalse(mOnCanceledCalled); |
| 294 assertFalse(mOnErrorCalled); | 321 assertFalse(mOnErrorCalled); |
| 295 assertNull(mError); | 322 assertNull(mError); |
| 296 mResponseStep = ResponseStep.ON_CANCELED; | 323 mResponseStep = ResponseStep.ON_CANCELED; |
| 297 mResponseInfo = info; | 324 mResponseInfo = info; |
| 298 | 325 |
| 299 mOnCanceledCalled = true; | 326 mOnCanceledCalled = true; |
| 300 openDone(); | 327 openDone(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } | 393 } |
| 367 }; | 394 }; |
| 368 if (mFailureType == FailureType.CANCEL_ASYNC | 395 if (mFailureType == FailureType.CANCEL_ASYNC |
| 369 || mFailureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE) { | 396 || mFailureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE) { |
| 370 getExecutor().execute(task); | 397 getExecutor().execute(task); |
| 371 } else { | 398 } else { |
| 372 task.run(); | 399 task.run(); |
| 373 } | 400 } |
| 374 return mFailureType != FailureType.CANCEL_ASYNC_WITHOUT_PAUSE; | 401 return mFailureType != FailureType.CANCEL_ASYNC_WITHOUT_PAUSE; |
| 375 } | 402 } |
| 403 |
| 404 /** |
| 405 * Checks whether callback methods are invoked on the correct thread. |
| 406 */ |
| 407 private void checkOnValidThread() { |
| 408 if (!mUseDirectExecutor) { |
| 409 assertEquals(mExecutorThread, Thread.currentThread()); |
| 410 } |
| 411 } |
| 376 } | 412 } |
| OLD | NEW |