1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.input;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import java.io.EOFException;
26 import java.io.IOException;
27 import java.io.InputStream;
28
29 import org.junit.jupiter.api.Test;
30 import org.junit.jupiter.params.ParameterizedTest;
31 import org.junit.jupiter.params.provider.MethodSource;
32 import org.junit.platform.commons.util.StringUtils;
33
34
35
36
37 public class NullInputStreamTest {
38
39 private static final class TestNullInputStream extends NullInputStream {
40
41 TestNullInputStream(final int size) {
42 super(size);
43 }
44
45 TestNullInputStream(final int size, final boolean markSupported, final boolean throwEofException) {
46 super(size, markSupported, throwEofException);
47 }
48
49 @Override
50 protected int processByte() {
51 return (int) getPosition() - 1;
52 }
53
54 @Override
55 protected void processBytes(final byte[] bytes, final int offset, final int length) {
56 final int startPos = (int) getPosition() - length;
57 for (int i = offset; i < length; i++) {
58 bytes[i] = (byte) (startPos + i);
59 }
60 }
61
62 }
63
64
65 private static final String MARK_RESET_NOT_SUPPORTED = "mark/reset not supported";
66
67 @SuppressWarnings("resource")
68 @ParameterizedTest
69 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
70 public void testAvailableAfterClose(final int len) throws Exception {
71 final InputStream shadow;
72 try (InputStream in = new TestNullInputStream(len, false, false)) {
73 assertEquals(len, in.available());
74 shadow = in;
75 }
76 assertEquals(0, shadow.available());
77 }
78
79 @ParameterizedTest
80 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
81 public void testAvailableAfterOpen(final int len) throws Exception {
82 try (InputStream in = new TestNullInputStream(len, false, false)) {
83 assertEquals(len, in.available());
84 }
85 }
86
87 @SuppressWarnings("deprecation")
88 @Test
89 public void testDeprecatedSingleton() throws Exception {
90 assertNotNull(NullInputStream.INSTANCE);
91 }
92
93 @Test
94 public void testEOFException() throws Exception {
95 try (InputStream input = new TestNullInputStream(2, false, true)) {
96 assertEquals(0, input.read(), "Read 1");
97 assertEquals(1, input.read(), "Read 2");
98 assertThrows(EOFException.class, () -> input.read());
99 }
100 }
101
102 @Test
103 public void testMarkAndReset() throws Exception {
104 int position = 0;
105 final int readLimit = 10;
106 try (InputStream input = new TestNullInputStream(100, true, false)) {
107
108 assertTrue(input.markSupported(), "Mark Should be Supported");
109
110
111 final IOException noMarkException = assertThrows(IOException.class, input::reset);
112 assertEquals("No position has been marked", noMarkException.getMessage(), "No Mark IOException message");
113
114 for (; position < 3; position++) {
115 assertEquals(position, input.read(), "Read Before Mark [" + position + "]");
116 }
117
118
119 input.mark(readLimit);
120
121
122 for (int i = 0; i < 3; i++) {
123 assertEquals(position + i, input.read(), "Read After Mark [" + i + "]");
124 }
125
126
127 input.reset();
128
129
130 for (int i = 0; i < readLimit + 1; i++) {
131 assertEquals(position + i, input.read(), "Read After Reset [" + i + "]");
132 }
133
134
135 final IOException resetException = assertThrows(IOException.class, input::reset, "Read limit exceeded, expected IOException");
136 assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readLimit + "]", resetException.getMessage(),
137 "Read limit IOException message");
138 }
139 }
140
141 @Test
142 public void testMarkNotSupported() throws Exception {
143 try (InputStream input = new TestNullInputStream(100, false, true)) {
144 assertFalse(input.markSupported(), "Mark Should NOT be Supported");
145
146 final UnsupportedOperationException markException = assertThrows(UnsupportedOperationException.class, () -> input.mark(5));
147 assertEquals(MARK_RESET_NOT_SUPPORTED, markException.getMessage(), "mark() error message");
148
149 final UnsupportedOperationException resetException = assertThrows(UnsupportedOperationException.class, input::reset);
150 assertEquals(MARK_RESET_NOT_SUPPORTED, resetException.getMessage(), "reset() error message");
151 }
152 }
153
154 @Test
155 public void testRead() throws Exception {
156 final int size = 5;
157 try (InputStream input = new TestNullInputStream(size)) {
158 for (int i = 0; i < size; i++) {
159 assertEquals(size - i, input.available(), "Check Size [" + i + "]");
160 assertEquals(i, input.read(), "Check Value [" + i + "]");
161 }
162 assertEquals(0, input.available(), "Available after contents all read");
163
164
165 assertEquals(-1, input.read(), "End of File");
166 assertEquals(0, input.available(), "Available after End of File");
167
168
169 assertEquals(-1, input.read(), "End of File");
170
171
172 input.close();
173 assertEquals(0, input.available(), "Available after close");
174 }
175 }
176
177 @Test
178 public void testReadAfterClose() throws Exception {
179 try (InputStream in = new NullInputStream()) {
180 assertEquals(0, in.available());
181 in.close();
182 assertThrows(IOException.class, in::read);
183 }
184 }
185
186 @ParameterizedTest
187 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
188 public void testReadAfterClose(final int len) throws Exception {
189 try (InputStream in = new TestNullInputStream(len, false, false)) {
190 assertEquals(len, in.available());
191 in.close();
192 assertThrows(IOException.class, in::read);
193 }
194 }
195
196 @Test
197 public void testReadByteArray() throws Exception {
198 final byte[] bytes = new byte[10];
199 try (NullInputStream input = new TestNullInputStream(15)) {
200
201
202 final int count1 = input.read(bytes);
203 assertEquals(bytes.length, count1, "Read 1");
204 for (int i = 0; i < count1; i++) {
205 assertEquals(i, bytes[i], "Check Bytes 1");
206 }
207
208
209 final int count2 = input.read(bytes);
210 assertEquals(5, count2, "Read 2");
211 for (int i = 0; i < count2; i++) {
212 assertEquals(count1 + i, bytes[i], "Check Bytes 2");
213 }
214
215
216 final int count3 = input.read(bytes);
217 assertEquals(-1, count3, "Read 3 (EOF)");
218
219
220 final int count4 = input.read(bytes);
221 assertEquals(-1, count4, "Read 4 (EOF)");
222
223
224 input.init();
225
226
227 final int offset = 2;
228 final int len = 4;
229 final int count5 = input.read(bytes, offset, len);
230 assertEquals(len, count5, "Read 5");
231 for (int i = offset; i < len; i++) {
232 assertEquals(i, bytes[i], "Check Bytes 2");
233 }
234 }
235 }
236
237 @Test
238 public void testReadByteArrayAfterClose() throws Exception {
239 try (InputStream in = new NullInputStream()) {
240 assertEquals(0, in.available());
241 in.close();
242 assertEquals(0, in.read(new byte[0]));
243 assertThrows(IOException.class, () -> in.read(new byte[2]));
244 }
245 }
246
247 @Test
248 public void testReadByteArrayIntIntAfterClose() throws Exception {
249 try (InputStream in = new NullInputStream()) {
250 assertEquals(0, in.available());
251 in.close();
252 assertEquals(0, in.read(new byte[0], 0, 1));
253 assertEquals(0, in.read(new byte[1], 0, 0));
254 assertThrows(IOException.class, () -> in.read(new byte[2], 0, 1));
255 }
256 }
257
258 @Test
259 public void testReadByteArrayThrowAtEof() throws Exception {
260 final byte[] bytes = new byte[10];
261 try (NullInputStream input = new TestNullInputStream(15, true, true)) {
262
263
264 final int count1 = input.read(bytes);
265 assertEquals(bytes.length, count1, "Read 1");
266 for (int i = 0; i < count1; i++) {
267 assertEquals(i, bytes[i], "Check Bytes 1");
268 }
269
270
271 final int count2 = input.read(bytes);
272 assertEquals(5, count2, "Read 2");
273 for (int i = 0; i < count2; i++) {
274 assertEquals(count1 + i, bytes[i], "Check Bytes 2");
275 }
276
277
278 final IOException e1 = assertThrows(EOFException.class, () -> input.read(bytes));
279 assertTrue(StringUtils.isNotBlank(e1.getMessage()));
280
281
282 final IOException e2 = assertThrows(EOFException.class, () -> input.read(bytes));
283 assertTrue(StringUtils.isNotBlank(e2.getMessage()));
284
285
286 input.init();
287
288
289 final int offset = 2;
290 final int len = 4;
291 final int count5 = input.read(bytes, offset, len);
292 assertEquals(len, count5, "Read 5");
293 for (int i = offset; i < len; i++) {
294 assertEquals(i, bytes[i], "Check Bytes 2");
295 }
296 }
297 }
298
299 @Test
300 public void testReadThrowAtEof() throws Exception {
301 final int size = 5;
302 try (InputStream input = new TestNullInputStream(size, true, true)) {
303 for (int i = 0; i < size; i++) {
304 assertEquals(size - i, input.available(), "Check Size [" + i + "]");
305 assertEquals(i, input.read(), "Check Value [" + i + "]");
306 }
307 assertEquals(0, input.available(), "Available after contents all read");
308
309
310 final IOException e1 = assertThrows(EOFException.class, input::read);
311 assertTrue(StringUtils.isNotBlank(e1.getMessage()));
312
313
314 final IOException e2 = assertThrows(EOFException.class, input::read);
315 assertTrue(StringUtils.isNotBlank(e2.getMessage()));
316
317
318 input.close();
319 assertEquals(0, input.available(), "Available after close");
320 }
321 }
322
323 @Test
324 public void testSkip() throws Exception {
325 try (InputStream input = new TestNullInputStream(10, true, false)) {
326 assertEquals(0, input.read(), "Read 1");
327 assertEquals(1, input.read(), "Read 2");
328 assertEquals(5, input.skip(5), "Skip 1");
329 assertEquals(7, input.read(), "Read 3");
330 assertEquals(2, input.skip(5), "Skip 2");
331 assertEquals(-1, input.skip(5), "Skip 3 (EOF)");
332 assertEquals(-1, input.skip(5), "Skip 3 (EOF)");
333 }
334 }
335
336 @Test
337 public void testSkipThrowAtEof() throws Exception {
338 try (InputStream input = new TestNullInputStream(10, true, true)) {
339 assertEquals(0, input.read(), "Read 1");
340 assertEquals(1, input.read(), "Read 2");
341 assertEquals(5, input.skip(5), "Skip 1");
342 assertEquals(7, input.read(), "Read 3");
343 assertEquals(2, input.skip(5), "Skip 2");
344
345 final IOException e1 = assertThrows(EOFException.class, () -> input.skip(5), "Skip 3 (EOF)");
346 assertTrue(StringUtils.isNotBlank(e1.getMessage()));
347
348 final IOException e2 = assertThrows(IOException.class, () -> input.skip(5), "Expected IOException for skipping after end of file");
349 assertTrue(StringUtils.isNotBlank(e2.getMessage()));
350 }
351 }
352 }