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

Side by Side Diff: components/cronet/android/test/javatests/src/org/chromium/net/TestDataProvider.java

Issue 849903002: [Cronet] Upload support for async APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.net;
6
7 import java.nio.ByteBuffer;
8 import java.util.ArrayList;
9 import java.util.concurrent.Executor;
10
11 /**
12 * An UploadDataProvider implementation used in tests.
13 */
14 class TestUploadDataProvider implements UploadDataProvider {
15 // Indicates whether all success callbacks are synchronous or asynchronous.
16 // Doesn't apply to errors.
17 enum SuccessCallbackMode {
18 SYNC,
19 ASYNC
20 };
21
22 // Indicates whether failures should throw exceptions, invoke callbacks
23 // synchronously, or invoke callback asynchronously.
24 enum FailMode {
25 NONE,
26 THROWN,
27 CALLBACK_SYNC,
28 CALLBACK_ASYNC
29 };
30
31 private ArrayList<byte[]> mReads = new ArrayList<byte[]>();
32 private final SuccessCallbackMode mSuccessCallbackMode;
33 private final Executor mExecutor;
34
35 private boolean mChunked = false;
36
37 // Index of read to fail on.
38 private int mReadFailIndex = -1;
39 // Indicates how to fail on a read.
40 private FailMode mReadFailMode = FailMode.NONE;
41
42 private FailMode mRewindFailMode = FailMode.NONE;
43
44 private int mNumReadCalls = 0;
45 private int mNumRewindCalls = 0;
46
47 private int mNextRead = 0;
48 private boolean mStarted = false;
49 private boolean mReadPending = false;
50 private boolean mRewindPending = false;
51 // Used to ensure there are no read/rewind requests after a failure.
52 private boolean mFailed = false;
53
54 TestUploadDataProvider(SuccessCallbackMode successCallbackMode,
55 Executor executor) {
56 mSuccessCallbackMode = successCallbackMode;
57 mExecutor = executor;
58 }
59
60 // Adds the result to be returned by a successful read request. The
61 // returned bytes must all fit within the read buffer provided by Cronet.
62 // After a rewind, if there is one, all reads will be repeated.
63 public void addRead(byte[] read) {
64 if (mStarted) {
65 throw new IllegalStateException("Adding bytes after read");
66 }
67 mReads.add(read);
68 }
69
70 public void setReadFailure(int readFailIndex, FailMode readFailMode) {
71 mReadFailIndex = readFailIndex;
72 mReadFailMode = readFailMode;
73 }
74
75 public void setRewindFailure(FailMode rewindFailMode) {
76 mRewindFailMode = rewindFailMode;
77 }
78
79 public void setChunked(boolean chunked) {
80 mChunked = chunked;
81 }
82
83 public int getNumReadCalls() {
84 return mNumReadCalls;
85 }
86
87 public int getNumRewindCalls() {
88 return mNumRewindCalls;
89 }
90
91 /**
92 * Returns the cumulative length of all data added by calls to addRead.
93 */
94 @Override
95 public long getLength() {
96 if (mChunked) {
97 return -1;
98 }
99 long length = 0;
100 for (byte[] read : mReads) {
101 length += read.length;
102 }
103 return length;
104 }
105
106 @Override
107 public void read(final UploadDataSink uploadDataSink,
108 final ByteBuffer byteBuffer) {
109 int currentReadCall = mNumReadCalls;
110 ++mNumReadCalls;
111 assertIdle();
112
113 if (maybeFailRead(currentReadCall, uploadDataSink)) {
114 mFailed = true;
115 return;
116 }
117
118 mReadPending = true;
119 mStarted = true;
120
121 final boolean finalChunk = (mChunked && mNextRead == mReads.size());
122 if (mNextRead < mReads.size()) {
123 if ((byteBuffer.limit() - byteBuffer.position())
124 < mReads.get(mNextRead).length) {
125 throw new IllegalStateException(
126 "Read buffer smaller than expected.");
127 }
128 byteBuffer.put(mReads.get(mNextRead));
129 ++mNextRead;
130 } else if (!finalChunk) {
131 throw new IllegalStateException(
132 "Too many reads: " + mNextRead);
133 }
134
135 Runnable completeRunnable = new Runnable() {
136 @Override
137 public void run() {
138 mReadPending = false;
139 uploadDataSink.onReadSucceeded(finalChunk);
140 }
141 };
142 if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
143 completeRunnable.run();
144 } else {
145 mExecutor.execute(completeRunnable);
146 }
147 }
148
149 public void rewind(final UploadDataSink uploadDataSink) {
150 ++mNumRewindCalls;
151 assertIdle();
152
153 if (maybeFailRewind(uploadDataSink)) {
154 mFailed = true;
155 return;
156 }
157
158 if (mNextRead == 0) {
159 // Should never try and rewind when rewinding does nothing.
160 throw new IllegalStateException(
161 "Unexpected rewind when already at beginning");
162 }
163
164 mRewindPending = true;
165 mNextRead = 0;
166
167 Runnable completeRunnable = new Runnable() {
168 @Override
169 public void run() {
170 mRewindPending = false;
171 uploadDataSink.onRewindSucceeded();
172 }
173 };
174 if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
175 completeRunnable.run();
176 } else {
177 mExecutor.execute(completeRunnable);
178 }
179 }
180
181 private void assertIdle() {
182 if (mReadPending) {
183 throw new IllegalStateException("Unexpected operation during read");
184 }
185 if (mRewindPending) {
186 throw new IllegalStateException(
187 "Unexpected operation during rewind");
188 }
189 if (mFailed) {
190 throw new IllegalStateException(
191 "Unexpected operation after failure");
192 }
193 }
194
195 private boolean maybeFailRead(int readIndex,
196 final UploadDataSink uploadDataSink) {
197 if (readIndex != mReadFailIndex)
198 return false;
199
200 switch (mReadFailMode) {
201 case THROWN:
202 throw new IllegalStateException("Thrown read failure");
203 case CALLBACK_SYNC:
204 uploadDataSink.onReadError(
205 new IllegalStateException("Sync read failure"));
206 return true;
207 case CALLBACK_ASYNC:
208 Runnable errorRunnable = new Runnable() {
209 @Override
210 public void run() {
211 uploadDataSink.onReadError(
212 new IllegalStateException("Async read failure")) ;
213 }
214 };
215 mExecutor.execute(errorRunnable);
216 return true;
217 default:
218 return false;
219 }
220 }
221
222 private boolean maybeFailRewind(final UploadDataSink uploadDataSink) {
223 switch (mRewindFailMode) {
224 case THROWN:
225 throw new IllegalStateException("Thrown rewind failure");
226 case CALLBACK_SYNC:
227 uploadDataSink.onRewindError(
228 new IllegalStateException("Sync rewind failure"));
229 return true;
230 case CALLBACK_ASYNC:
231 Runnable errorRunnable = new Runnable() {
232 @Override
233 public void run() {
234 uploadDataSink.onRewindError(new IllegalStateException(
235 "Async rewind failure"));
236 }
237 };
238 mExecutor.execute(errorRunnable);
239 return true;
240 default:
241 return false;
242 }
243 }
244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698