Skip to content

Commit 8ff5b79

Browse files
author
Niall Pemberton
committed
IO-94 - New MockReader implementation
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@454248 13f79535-47bb-0310-9956-ffa450edef68
1 parent 166fc85 commit 8ff5b79

2 files changed

Lines changed: 546 additions & 0 deletions

File tree

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.commons.io.input;
18+
19+
import java.io.EOFException;
20+
import java.io.IOException;
21+
import java.io.Reader;
22+
23+
/**
24+
* A mock {@link Reader} for testing purposes.
25+
* <p>
26+
* This implementation provides a light weight mock
27+
* object for testing with a {@link Reader}
28+
* where the contents don't matter.
29+
* <p>
30+
* One use case would be for testing the handling of
31+
* large {@link Reader} as it can emulate that
32+
* scenario without the overhead of actually processing
33+
* large numbers of characters - significantly speeding up
34+
* test execution times.
35+
* <p>
36+
* Alternatively, if some kind of data is required as part
37+
* of a test the <code>processChar()</code> and
38+
* <code>processChars()</code> methods can be implemented to generate
39+
* test data.
40+
*
41+
*
42+
* @since Commons IO 1.3
43+
* @version $Revision$
44+
*/
45+
public class MockReader extends Reader {
46+
47+
private long size;
48+
private long position;
49+
private long mark = -1;
50+
private long readlimit;
51+
private boolean eof;
52+
private boolean throwEofException;
53+
private boolean markSupported;
54+
55+
/**
56+
* Create a mock {@link Reader} of the specified size.
57+
*
58+
* @param size The size of the mock Reader.
59+
*/
60+
public MockReader(long size) {
61+
this(size, true, false);
62+
}
63+
64+
/**
65+
* Create a mock {@link Reader} of the specified
66+
* size and option settings.
67+
*
68+
* @param size The size of the mock Reader.
69+
* @param markSupported Whether this instance will support
70+
* the <code>mark()</code> functionality.
71+
* @param throwEofException Whether this implementation
72+
* will throw an {@link EOFException} or return -1 when the
73+
* end of file is reached.
74+
*/
75+
public MockReader(long size, boolean markSupported, boolean throwEofException) {
76+
this.size = size;
77+
this.markSupported = markSupported;
78+
this.throwEofException = throwEofException;
79+
}
80+
81+
/**
82+
* Return the current position.
83+
*
84+
* @return the current position.
85+
*/
86+
public long getPosition() {
87+
return position;
88+
}
89+
90+
/**
91+
* Return the size of this Mock {@link Reader}
92+
*
93+
* @return the size of the mock Reader.
94+
*/
95+
public long getSize() {
96+
return size;
97+
}
98+
99+
/**
100+
* Close this Reader - resets the internal state to
101+
* the initial values.
102+
*
103+
* @throws IOException If an error occurs.
104+
*/
105+
public void close() throws IOException {
106+
eof = false;
107+
position = 0;
108+
mark = -1;
109+
}
110+
111+
/**
112+
* Mark the current position.
113+
*
114+
* @param readlimit The number of characters before this marked position
115+
* is invalid.
116+
* @throws UnsupportedOperationException if mark is not supported.
117+
*/
118+
public synchronized void mark(int readlimit) {
119+
if (!markSupported) {
120+
throw new UnsupportedOperationException("Mark not supported");
121+
}
122+
mark = position;
123+
this.readlimit = readlimit;
124+
}
125+
126+
/**
127+
* Indicates whether <i>mark</i> is supported.
128+
*
129+
* @return Whether <i>mark</i> is supported or not.
130+
*/
131+
public boolean markSupported() {
132+
return markSupported;
133+
}
134+
135+
/**
136+
* Read a character.
137+
*
138+
* @return Either The character value returned by <code>processChar()</code>
139+
* or <code>-1</code> if the end of file has been reached and
140+
* <code>throwEofException</code> is set to <code>false</code>.
141+
* @throws EOFException if the end of file is reached and
142+
* <code>throwEofException</code> is set to <code>true</code>.
143+
* @throws IOException if trying to read past the end of file.
144+
*/
145+
public int read() throws IOException {
146+
if (eof) {
147+
throw new IOException("Read after end of file");
148+
}
149+
if (position == size) {
150+
return doEndOfFile();
151+
}
152+
position++;
153+
return processChar();
154+
}
155+
156+
/**
157+
* Read some characters into the specified array.
158+
*
159+
* @param chars The character array to read into
160+
* @return The number of characters read or <code>-1</code>
161+
* if the end of file has been reached and
162+
* <code>throwEofException</code> is set to <code>false</code>.
163+
* @throws EOFException if the end of file is reached and
164+
* <code>throwEofException</code> is set to <code>true</code>.
165+
* @throws IOException if trying to read past the end of file.
166+
*/
167+
public int read(char[] chars) throws IOException {
168+
return read(chars, 0, chars.length);
169+
}
170+
171+
/**
172+
* Read the specified number characters into an array.
173+
*
174+
* @param chars The character array to read into.
175+
* @param offset The offset to start reading characters into.
176+
* @param length The number of characters to read.
177+
* @return The number of characters read or <code>-1</code>
178+
* if the end of file has been reached and
179+
* <code>throwEofException</code> is set to <code>false</code>.
180+
* @throws EOFException if the end of file is reached and
181+
* <code>throwEofException</code> is set to <code>true</code>.
182+
* @throws IOException if trying to read past the end of file.
183+
*/
184+
public int read(char[] chars, int offset, int length) throws IOException {
185+
if (eof) {
186+
throw new IOException("Read after end of file");
187+
}
188+
if (position == size) {
189+
return doEndOfFile();
190+
}
191+
position += length;
192+
int returnLength = length;
193+
if (position > size) {
194+
returnLength = length - (int)(position - size);
195+
position = size;
196+
}
197+
processChars(chars, offset, returnLength);
198+
return returnLength;
199+
}
200+
201+
/**
202+
* Reset the stream to the point when mark was last called.
203+
*
204+
* @throws UnsupportedOperationException if mark is not supported.
205+
* @throws IOException If no position has been marked
206+
* or the read limit has been exceed since the last position was
207+
* marked.
208+
*/
209+
public synchronized void reset() throws IOException {
210+
if (!markSupported) {
211+
throw new UnsupportedOperationException("Mark not supported");
212+
}
213+
if (mark < 0) {
214+
throw new IOException("No position has been marked");
215+
}
216+
if (position > (mark + readlimit)) {
217+
throw new IOException("Marked position [" + mark +
218+
"] is no longer valid - passed the read limit [" +
219+
readlimit + "]");
220+
}
221+
position = mark;
222+
eof = false;
223+
}
224+
225+
/**
226+
* Skip a specified number of characters.
227+
*
228+
* @param numberOfChars The number of characters to skip.
229+
* @return The number of characters skipped or <code>-1</code>
230+
* if the end of file has been reached and
231+
* <code>throwEofException</code> is set to <code>false</code>.
232+
* @throws EOFException if the end of file is reached and
233+
* <code>throwEofException</code> is set to <code>true</code>.
234+
* @throws IOException if trying to read past the end of file.
235+
*/
236+
public long skip(long numberOfChars) throws IOException {
237+
if (eof) {
238+
throw new IOException("Skip after end of file");
239+
}
240+
if (position == size) {
241+
return doEndOfFile();
242+
}
243+
position += numberOfChars;
244+
long returnLength = numberOfChars;
245+
if (position > size) {
246+
returnLength = numberOfChars - (position - size);
247+
position = size;
248+
}
249+
return returnLength;
250+
}
251+
252+
/**
253+
* Return a character value for the <code>read()</code> method.
254+
* <p>
255+
* <strong>N.B.</strong> This implementation returns
256+
* zero.
257+
*
258+
* @return This implementation always returns zero.
259+
*/
260+
protected int processChar() {
261+
return 0;
262+
}
263+
264+
/**
265+
* Process the characters for the <code>read(char[], offset, length)</code>
266+
* method.
267+
* <p>
268+
* <strong>N.B.</strong> This implementation leaves the character
269+
* array unchanged.
270+
*
271+
* @param chars The character array
272+
* @param offset The offset to start at.
273+
* @param length The number of characters.
274+
*/
275+
protected void processChars(char[] chars, int offset, int length) {
276+
}
277+
278+
/**
279+
* Handle End of File.
280+
*
281+
* @return <code>-1</code> if <code>throwEofException</code> is
282+
* set to <code>false</code>
283+
* @throws EOFException if <code>throwEofException</code> is set
284+
* to <code>true</code>.
285+
*/
286+
private int doEndOfFile() throws EOFException {
287+
eof = true;
288+
if (throwEofException) {
289+
throw new EOFException();
290+
}
291+
return -1;
292+
}
293+
}

0 commit comments

Comments
 (0)