View Javadoc
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    *      https://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  
18  package org.apache.commons.io.input;
19  
20  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotEquals;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.File;
28  import java.io.FileNotFoundException;
29  import java.io.IOException;
30  import java.io.RandomAccessFile;
31  import java.nio.charset.StandardCharsets;
32  import java.nio.file.Path;
33  import java.nio.file.Paths;
34  import java.nio.file.StandardOpenOption;
35  
36  import org.apache.commons.io.RandomAccessFileMode;
37  import org.apache.commons.io.output.ByteArrayOutputStream;
38  import org.junit.jupiter.api.Test;
39  
40  /**
41   * Tests {@link RandomAccessFileInputStream}.
42   */
43  class RandomAccessFileInputStreamTest {
44  
45      private static final String DATA_FILE_NAME = "src/test/resources/org/apache/commons/io/test-file-iso8859-1.bin";
46      private static final Path DATA_PATH = Paths.get(DATA_FILE_NAME);
47      private static final int DATA_FILE_LEN = 1430;
48  
49      private RandomAccessFile createRandomAccessFile() throws FileNotFoundException {
50          return RandomAccessFileMode.READ_ONLY.create(DATA_FILE_NAME);
51      }
52  
53      @SuppressWarnings("resource")
54      @Test
55      void testAvailableAfterClose() throws IOException {
56          try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
57                  .setRandomAccessFile(createRandomAccessFile())
58                  .setCloseOnClose(true)
59                  .get()) {
60              inputStream.close();
61              assertEquals(0, inputStream.available());
62          }
63      }
64  
65      @Test
66      void testAvailableAfterOpen() throws IOException {
67          try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
68                  .setRandomAccessFile(createRandomAccessFile())
69                  .setCloseOnClose(true)
70                  .get()) {
71              assertEquals(DATA_FILE_LEN, inputStream.available());
72          }
73      }
74  
75      @Test
76      void testAvailableLong() throws IOException {
77          try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
78                  .setRandomAccessFile(createRandomAccessFile())
79                  .setCloseOnClose(true)
80                  .get()) {
81              assertEquals(DATA_FILE_LEN, inputStream.availableLong());
82          }
83      }
84  
85      @SuppressWarnings("resource") // instance variable access
86      @Test
87      void testBuilderFile() throws IOException {
88          try (RandomAccessFile file = createRandomAccessFile()) {
89              try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setFile(new File(DATA_FILE_NAME)).get()) {
90                  assertFalse(inputStream.isCloseOnClose());
91                  assertNotEquals(-1, inputStream.getRandomAccessFile().read());
92              }
93              file.read();
94          }
95      }
96  
97      @Test
98      void testBuilderGet() {
99          // java.lang.IllegalStateException: origin == null
100         assertThrows(IllegalStateException.class, () -> RandomAccessFileInputStream.builder().get());
101     }
102 
103     @SuppressWarnings("resource") // instance variable access
104     @Test
105     void testBuilderPath() throws IOException {
106         try (RandomAccessFile file = createRandomAccessFile()) {
107             try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setPath(DATA_PATH).get()) {
108                 assertFalse(inputStream.isCloseOnClose());
109                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
110             }
111             file.read();
112         }
113     }
114 
115     @SuppressWarnings("resource") // instance variable access
116     @Test
117     void testBuilderPathOpenOptions() throws IOException {
118         try (RandomAccessFile file = createRandomAccessFile()) {
119             try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setPath(DATA_PATH).setOpenOptions(StandardOpenOption.READ)
120                     .get()) {
121                 assertFalse(inputStream.isCloseOnClose());
122                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
123             }
124             file.read();
125         }
126     }
127 
128     @SuppressWarnings("resource") // instance variable access
129     @Test
130     void testBuilderRandomAccessFile() throws IOException {
131         try (RandomAccessFile file = createRandomAccessFile()) {
132             try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setRandomAccessFile(file).get()) {
133                 assertFalse(inputStream.isCloseOnClose());
134                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
135             }
136             file.read();
137         }
138     }
139 
140     @SuppressWarnings("resource") // instance variable access
141     @Test
142     void testConstructorCloseOnCloseFalse() throws IOException {
143         try (RandomAccessFile file = createRandomAccessFile()) {
144             try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
145                     .setRandomAccessFile(createRandomAccessFile())
146                     .get()) {
147                 assertFalse(inputStream.isCloseOnClose());
148                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
149             }
150             file.read();
151         }
152     }
153 
154     @Test
155     void testCopy() throws IOException {
156         // @formatter:off
157         try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
158                 .setRandomAccessFile(createRandomAccessFile())
159                 .setCloseOnClose(true)
160                 .get()) {
161             // @formatter:on
162             // A Test Line.
163             try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
164                 // 0 and 12
165                 assertEquals(12, inputStream.copy(0, 12, baos));
166                 assertArrayEquals("A Test Line.".getBytes(StandardCharsets.ISO_8859_1), baos.toByteArray());
167                 // 0 and 1
168                 baos.reset();
169                 assertEquals(1, inputStream.copy(0, 1, baos));
170                 assertArrayEquals("A".getBytes(StandardCharsets.ISO_8859_1), baos.toByteArray());
171                 // 11 and 1
172                 baos.reset();
173                 assertEquals(1, inputStream.copy(11, 1, baos));
174                 assertArrayEquals(".".getBytes(StandardCharsets.ISO_8859_1), baos.toByteArray());
175                 // 1 and 10
176                 baos.reset();
177                 assertEquals(10, inputStream.copy(1, 10, baos));
178                 assertArrayEquals(" Test Line".getBytes(StandardCharsets.ISO_8859_1), baos.toByteArray());
179                 // next
180                 assertEquals('.', inputStream.read());
181             }
182         }
183     }
184 
185     @SuppressWarnings("resource") // instance variable access
186     @Test
187     void testDeprecatedConstructorCloseOnCloseTrue() throws IOException {
188         try (RandomAccessFile file = createRandomAccessFile()) {
189             try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, true)) {
190                 assertTrue(inputStream.isCloseOnClose());
191                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
192             }
193             assertThrows(IOException.class, file::read);
194         }
195     }
196 
197     @SuppressWarnings("resource") // instance variable access
198     @Test
199     void testDeprecatedConstructorRandomAccessFile() throws IOException {
200         try (RandomAccessFile file = createRandomAccessFile()) {
201             try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file)) {
202                 assertFalse(inputStream.isCloseOnClose());
203                 assertNotEquals(-1, inputStream.getRandomAccessFile().read());
204             }
205             file.read();
206         }
207     }
208 
209     @SuppressWarnings("deprecation")
210     @Test
211     void testDeprecatedConstructors() throws IOException {
212         try (RandomAccessFile randomAccessFile = createRandomAccessFile()) {
213             try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(randomAccessFile)) {
214                 assertFalse(inputStream.isCloseOnClose());
215                 assertEquals(randomAccessFile, inputStream.getRandomAccessFile());
216             }
217             try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(randomAccessFile, true)) {
218                 assertTrue(inputStream.isCloseOnClose());
219                 assertEquals(randomAccessFile, inputStream.getRandomAccessFile());
220             }
221             try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(randomAccessFile, false)) {
222                 assertFalse(inputStream.isCloseOnClose());
223                 assertEquals(randomAccessFile, inputStream.getRandomAccessFile());
224             }
225         }
226     }
227 
228     @SuppressWarnings("deprecation")
229     @Test
230     void testDeprecatedConstructorsNull() {
231         assertThrows(NullPointerException.class, () -> new RandomAccessFileInputStream(null));
232         assertThrows(NullPointerException.class, () -> new RandomAccessFileInputStream(null, true));
233         assertThrows(NullPointerException.class, () -> new RandomAccessFileInputStream(null, false));
234     }
235 
236     @Test
237     void testGetters() throws IOException {
238         try (RandomAccessFile file = createRandomAccessFile()) {
239             try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
240                     .setRandomAccessFile(file)
241                     .setCloseOnClose(true)
242                     .get()) {
243                 assertEquals(file, inputStream.getRandomAccessFile());
244                 assertTrue(inputStream.isCloseOnClose());
245             }
246         }
247     }
248 
249     @Test
250     void testRead() throws IOException {
251         try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
252                 .setRandomAccessFile(createRandomAccessFile())
253                 .setCloseOnClose(true)
254                 .get()) {
255             // A Test Line.
256             assertEquals('A', inputStream.read());
257             assertEquals(' ', inputStream.read());
258             assertEquals('T', inputStream.read());
259             assertEquals('e', inputStream.read());
260             assertEquals('s', inputStream.read());
261             assertEquals('t', inputStream.read());
262             assertEquals(' ', inputStream.read());
263             assertEquals('L', inputStream.read());
264             assertEquals('i', inputStream.read());
265             assertEquals('n', inputStream.read());
266             assertEquals('e', inputStream.read());
267             assertEquals('.', inputStream.read());
268             assertEquals(DATA_FILE_LEN - 12, inputStream.available());
269             assertEquals(DATA_FILE_LEN - 12, inputStream.availableLong());
270         }
271     }
272 
273     @Test
274     void testReadAfterClose() throws IOException {
275         try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
276                 .setRandomAccessFile(createRandomAccessFile())
277                 .setCloseOnClose(true)
278                 .get()) {
279             inputStream.close();
280             assertThrows(IOException.class, inputStream::read);
281         }
282     }
283 
284     @Test
285     void testReadByteArray() throws IOException {
286         try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
287                 .setRandomAccessFile(createRandomAccessFile())
288                 .setCloseOnClose(true)
289                 .get()) {
290             // A Test Line.
291             final int dataLen = 12;
292             final byte[] buffer = new byte[dataLen];
293             assertEquals(dataLen, inputStream.read(buffer));
294             assertArrayEquals("A Test Line.".getBytes(StandardCharsets.ISO_8859_1), buffer);
295             //
296             assertEquals(DATA_FILE_LEN - dataLen, inputStream.available());
297             assertEquals(DATA_FILE_LEN - dataLen, inputStream.availableLong());
298         }
299     }
300 
301     @Test
302     void testReadByteArrayBounds() throws IOException {
303         try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
304                 .setRandomAccessFile(createRandomAccessFile())
305                 .setCloseOnClose(true)
306                 .get()) {
307             // A Test Line.
308             final int dataLen = 12;
309             final byte[] buffer = new byte[dataLen];
310             assertEquals(dataLen, inputStream.read(buffer, 0, dataLen));
311             assertArrayEquals("A Test Line.".getBytes(StandardCharsets.ISO_8859_1), buffer);
312             //
313             assertEquals(DATA_FILE_LEN - dataLen, inputStream.available());
314             assertEquals(DATA_FILE_LEN - dataLen, inputStream.availableLong());
315         }
316     }
317 
318     @Test
319     void testSkip() throws IOException {
320 
321         try (RandomAccessFile file = createRandomAccessFile();
322              RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder()
323                     .setRandomAccessFile(file)
324                     .get()) {
325             assertEquals(0, inputStream.skip(-1));
326             assertEquals(0, inputStream.skip(Integer.MIN_VALUE));
327             assertEquals(0, inputStream.skip(0));
328             // A Test Line.
329             assertEquals('A', inputStream.read());
330             assertEquals(1, inputStream.skip(1));
331             assertEquals('T', inputStream.read());
332             assertEquals(1, inputStream.skip(1));
333             assertEquals('s', inputStream.read());
334             assertEquals(1, inputStream.skip(1));
335             assertEquals(' ', inputStream.read());
336             assertEquals(1, inputStream.skip(1));
337             assertEquals('i', inputStream.read());
338             assertEquals(1, inputStream.skip(1));
339             assertEquals('e', inputStream.read());
340             assertEquals(1, inputStream.skip(1));
341             //
342             assertEquals(DATA_FILE_LEN - 12, inputStream.available());
343             assertEquals(DATA_FILE_LEN - 12, inputStream.availableLong());
344             assertEquals(10, inputStream.skip(10));
345             assertEquals(DATA_FILE_LEN - 22, inputStream.availableLong());
346             //
347             final long avail = inputStream.availableLong();
348             assertEquals(avail, inputStream.skip(inputStream.availableLong()));
349             // At EOF
350             assertEquals(DATA_FILE_LEN, file.length());
351             assertEquals(DATA_FILE_LEN, file.getFilePointer());
352             //
353             assertEquals(0, inputStream.skip(1));
354             assertEquals(0, inputStream.skip(1000000000000L));
355         }
356     }
357 }