1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.build;
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.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 import java.io.Closeable;
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.io.RandomAccessFile;
32 import java.io.Reader;
33 import java.io.Writer;
34 import java.nio.ByteBuffer;
35 import java.nio.channels.ReadableByteChannel;
36 import java.nio.channels.SeekableByteChannel;
37 import java.nio.channels.WritableByteChannel;
38 import java.nio.charset.Charset;
39 import java.nio.charset.StandardCharsets;
40 import java.nio.file.Files;
41 import java.nio.file.OpenOption;
42 import java.nio.file.Path;
43 import java.nio.file.StandardOpenOption;
44 import java.util.Objects;
45
46 import org.apache.commons.io.FileUtils;
47 import org.apache.commons.io.IOUtils;
48 import org.apache.commons.io.build.AbstractOrigin.RandomAccessFileOrigin;
49 import org.junit.jupiter.api.AfterEach;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52 import org.junit.jupiter.api.io.TempDir;
53 import org.junit.jupiter.params.ParameterizedTest;
54 import org.junit.jupiter.params.provider.EnumSource;
55
56
57
58
59
60
61
62 public abstract class AbstractOriginTest<T, B extends AbstractOrigin<T, B>> {
63
64 protected static final String FILE_RES_RO = "/org/apache/commons/io/test-file-20byteslength.bin";
65 protected static final String FILE_NAME_RO = "src/test/resources" + FILE_RES_RO;
66 protected static final String FILE_NAME_RW = AbstractOriginTest.class.getSimpleName() + ".txt";
67 private static final int RO_LENGTH = 20;
68
69 protected AbstractOrigin<T, B> originRo;
70 protected AbstractOrigin<T, B> originRw;
71
72 @TempDir
73 protected Path tempPath;
74
75 @BeforeEach
76 void beforeEach() throws IOException {
77 setOriginRo(newOriginRo());
78 resetOriginRw();
79 setOriginRw(newOriginRw());
80 }
81
82 private void checkRead(final ReadableByteChannel channel) throws IOException {
83 final ByteBuffer buffer = ByteBuffer.allocate(RO_LENGTH);
84 int read = channel.read(buffer);
85 assertEquals(RO_LENGTH, read);
86 assertArrayEquals(getFixtureByteArray(), buffer.array());
87
88 buffer.clear();
89 read = channel.read(buffer);
90 assertEquals(-1, read);
91 }
92
93 private void checkWrite(final WritableByteChannel channel) throws IOException {
94 final ByteBuffer buffer = ByteBuffer.wrap(getFixtureByteArray());
95 final int written = channel.write(buffer);
96 assertEquals(RO_LENGTH, written);
97 }
98
99 @AfterEach
100 void cleanup() {
101 final T originRo = getOriginRo().get();
102 if (originRo instanceof Closeable) {
103 IOUtils.closeQuietly((Closeable) originRo);
104 }
105 final T originRw = getOriginRw().get();
106 if (originRw instanceof Closeable) {
107 IOUtils.closeQuietly((Closeable) originRw);
108 }
109 }
110
111 byte[] getFixtureByteArray() throws IOException {
112 return IOUtils.resourceToByteArray(FILE_RES_RO);
113 }
114
115 String getFixtureString() throws IOException {
116 return IOUtils.resourceToString(FILE_RES_RO, StandardCharsets.UTF_8);
117 }
118
119 protected AbstractOrigin<T, B> getOriginRo() {
120 return Objects.requireNonNull(originRo, "originRo");
121 }
122
123 protected AbstractOrigin<T, B> getOriginRw() {
124 return Objects.requireNonNull(originRw, "originRw");
125 }
126
127 @SuppressWarnings("resource")
128 private boolean isValid(final RandomAccessFile raf) throws IOException {
129 return Objects.requireNonNull(raf).getFD().valid();
130 }
131
132 protected abstract B newOriginRo() throws IOException;
133
134 protected abstract B newOriginRw() throws IOException;
135
136 protected void resetOriginRw() throws IOException {
137
138 }
139
140 protected void setOriginRo(final AbstractOrigin<T, B> origin) {
141 this.originRo = origin;
142 }
143
144 protected void setOriginRw(final AbstractOrigin<T, B> origin) {
145 this.originRw = origin;
146 }
147
148 @Test
149 void testGetByteArray() throws IOException {
150 assertArrayEquals(getFixtureByteArray(), getOriginRo().getByteArray());
151 }
152
153 @Test
154 void testGetByteArrayAt_0_0() throws IOException {
155 assertArrayEquals(new byte[] {}, getOriginRo().getByteArray(0, 0));
156 }
157
158 @Test
159 void testGetByteArrayAt_0_1() throws IOException {
160 assertArrayEquals(new byte[] { '1' }, getOriginRo().getByteArray(0, 1));
161 }
162
163 @Test
164 void testGetByteArrayAt_1_1() throws IOException {
165 assertArrayEquals(new byte[] { '2' }, getOriginRo().getByteArray(1, 1));
166 }
167
168 @Test
169 void testGetCharSequence() throws IOException {
170 final CharSequence charSequence = getOriginRo().getCharSequence(StandardCharsets.UTF_8);
171 assertNotNull(charSequence);
172 assertEquals(getFixtureString(), charSequence.toString());
173 }
174
175 @Test
176 void testGetFile() throws IOException {
177 testGetFile(getOriginRo().getFile(), RO_LENGTH);
178 FileUtils.touch(getOriginRw().getFile());
179 testGetFile(getOriginRw().getFile(), 0);
180 }
181
182 private void testGetFile(final File file, final long expectedLen) throws IOException {
183 assertNotNull(file);
184 assertTrue(file.exists(), () -> "File does not exist: " + file);
185 final int length = FileUtils.readFileToByteArray(file).length;
186 assertEquals(length, expectedLen, () -> String.format("File %s, actual length=%,d", file, length));
187 }
188
189 @Test
190 void testGetInputStream() throws IOException {
191 try (InputStream inputStream = getOriginRo().getInputStream()) {
192 assertNotNull(inputStream);
193 assertArrayEquals(getFixtureByteArray(), IOUtils.toByteArray(inputStream));
194 }
195 }
196
197 @Test
198 void testGetOutputStream() throws IOException {
199 try (OutputStream output = getOriginRw().getOutputStream()) {
200 assertNotNull(output);
201 }
202 }
203
204 @Test
205 void testGetPath() throws IOException {
206 testGetPath(getOriginRo().getPath(), RO_LENGTH);
207 FileUtils.touch(getOriginRw().getPath().toFile());
208 testGetPath(getOriginRw().getPath(), 0);
209 }
210
211 private void testGetPath(final Path path, final long expectedLen) throws IOException {
212 assertNotNull(path);
213 assertTrue(Files.exists(path));
214 final int length = Files.readAllBytes(path).length;
215 assertEquals(length, expectedLen, () -> String.format("Path %s, actual length=%,d", path, length));
216 }
217
218 @Test
219 void testGetRandomAccessFile() throws IOException {
220
221 try (RandomAccessFile raf = getOriginRo().getRandomAccessFile()) {
222 assertNotNull(raf);
223 assertTrue(isValid(raf));
224 }
225 final boolean isRafOriginRo = getOriginRo() instanceof RandomAccessFileOrigin;
226 final boolean isRafOriginRw = getOriginRw() instanceof RandomAccessFileOrigin;
227
228 try (RandomAccessFile raf = getOriginRo().getRandomAccessFile()) {
229 assertNotNull(raf);
230 assertFalse(isRafOriginRo && isValid(raf));
231 }
232
233 try (RandomAccessFile raf = getOriginRo().getRandomAccessFile(StandardOpenOption.READ)) {
234 assertNotNull(raf);
235 assertFalse(isRafOriginRo && isValid(raf));
236 }
237
238 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile(StandardOpenOption.WRITE)) {
239 assertNotNull(raf);
240 if (isRafOriginRw || getOriginRw().getFile() != null) {
241 assertTrue(isValid(raf), () -> getOriginRw().toString());
242 } else {
243
244 assertFalse(isValid(raf), () -> getOriginRw().toString());
245 }
246 }
247
248 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile(StandardOpenOption.READ, StandardOpenOption.WRITE)) {
249 assertNotNull(raf);
250 assertFalse(isRafOriginRw && isValid(raf));
251 }
252 }
253
254 @ParameterizedTest
255 @EnumSource(StandardOpenOption.class)
256 void testGetRandomAccessFile(final OpenOption openOption) throws IOException {
257
258 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile()) {
259 assertNotNull(raf);
260 assertTrue(isValid(raf));
261 }
262
263 final boolean isRafOrigin = getOriginRw() instanceof RandomAccessFileOrigin;
264 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile()) {
265 assertNotNull(raf);
266 assertFalse(isRafOrigin && isValid(raf));
267 }
268 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile(openOption)) {
269 assertNotNull(raf);
270 assertFalse(isRafOrigin && isValid(raf));
271 }
272 try (RandomAccessFile raf = getOriginRw().getRandomAccessFile(openOption)) {
273 assertNotNull(raf);
274 assertFalse(isRafOrigin && isValid(raf));
275 }
276 }
277
278 @Test
279 void testGetReadableByteChannel() throws IOException {
280 try (ReadableByteChannel channel = getOriginRo().getChannel(ReadableByteChannel.class, StandardOpenOption.READ)) {
281 final SeekableByteChannel seekable = channel instanceof SeekableByteChannel ? (SeekableByteChannel) channel : null;
282 assertNotNull(channel);
283 assertTrue(channel.isOpen());
284 if (seekable != null) {
285 assertEquals(0, seekable.position());
286 assertEquals(RO_LENGTH, seekable.size());
287 }
288 checkRead(channel);
289 if (seekable != null) {
290 assertEquals(RO_LENGTH, seekable.position());
291 }
292 }
293 }
294
295 @Test
296 void testGetReader() throws IOException {
297 try (Reader reader = getOriginRo().getReader(Charset.defaultCharset())) {
298 assertNotNull(reader);
299 }
300 setOriginRo(newOriginRo());
301 try (Reader reader = getOriginRo().getReader(null)) {
302 assertNotNull(reader);
303 }
304 setOriginRo(newOriginRo());
305 try (Reader reader = getOriginRo().getReader(StandardCharsets.UTF_8)) {
306 assertNotNull(reader);
307 assertEquals(getFixtureString(), IOUtils.toString(reader));
308 }
309 }
310
311 @Test
312 void testGetWritableByteChannel() throws IOException {
313 final boolean supportsRead;
314 try (WritableByteChannel channel = getOriginRw().getChannel(WritableByteChannel.class, StandardOpenOption.WRITE)) {
315 supportsRead = channel instanceof ReadableByteChannel;
316 final SeekableByteChannel seekable = channel instanceof SeekableByteChannel ? (SeekableByteChannel) channel : null;
317 assertNotNull(channel);
318 assertTrue(channel.isOpen());
319 if (seekable != null) {
320 assertEquals(0, seekable.position());
321 assertEquals(0, seekable.size());
322 }
323 checkWrite(channel);
324 if (seekable != null) {
325 assertEquals(RO_LENGTH, seekable.position());
326 assertEquals(RO_LENGTH, seekable.size());
327 }
328 }
329 if (supportsRead) {
330 setOriginRw(newOriginRw());
331 try (ReadableByteChannel channel = getOriginRw().getChannel(ReadableByteChannel.class, StandardOpenOption.READ)) {
332 assertNotNull(channel);
333 assertTrue(channel.isOpen());
334 checkRead(channel);
335 }
336 }
337 setOriginRw(newOriginRw());
338 try (WritableByteChannel channel = getOriginRw().getChannel(WritableByteChannel.class, StandardOpenOption.WRITE)) {
339 final SeekableByteChannel seekable = channel instanceof SeekableByteChannel ? (SeekableByteChannel) channel : null;
340 assertNotNull(channel);
341 assertTrue(channel.isOpen());
342 if (seekable != null) {
343 seekable.position(RO_LENGTH);
344 assertEquals(RO_LENGTH, seekable.position());
345 assertEquals(RO_LENGTH, seekable.size());
346
347 final int newSize = RO_LENGTH / 2;
348 seekable.truncate(newSize);
349 assertEquals(newSize, seekable.position());
350 assertEquals(newSize, seekable.size());
351
352 seekable.position(0);
353 assertEquals(0, seekable.position());
354 }
355 }
356 }
357
358 @Test
359 void testGetWriter() throws IOException {
360 try (Writer writer = getOriginRw().getWriter(Charset.defaultCharset())) {
361 assertNotNull(writer);
362 }
363 setOriginRw(newOriginRw());
364 try (Writer writer = getOriginRw().getWriter(null)) {
365 assertNotNull(writer);
366 }
367 }
368
369 @Test
370 void testSize() throws IOException {
371 assertEquals(RO_LENGTH, getOriginRo().getByteArray().length);
372 }
373 }