blob: 0e1be9a28c0b8e91c05b9eeb7be93b8b5f1b3cb4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.io.input;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.util.StringUtils;
/**
* Tests {@link NullInputStream}.
*/
public class NullInputStreamTest {
private static final class TestNullInputStream extends NullInputStream {
public TestNullInputStream(final int size) {
super(size);
}
public TestNullInputStream(final int size, final boolean markSupported, final boolean throwEofException) {
super(size, markSupported, throwEofException);
}
@Override
protected int processByte() {
return (int) getPosition() - 1;
}
@Override
protected void processBytes(final byte[] bytes, final int offset, final int length) {
final int startPos = (int) getPosition() - length;
for (int i = offset; i < length; i++) {
bytes[i] = (byte) (startPos + i);
}
}
}
/** Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. */
private static final String MARK_RESET_NOT_SUPPORTED = "mark/reset not supported";
@Test
public void testEOFException() throws Exception {
try (InputStream input = new TestNullInputStream(2, false, true)) {
assertEquals(0, input.read(), "Read 1");
assertEquals(1, input.read(), "Read 2");
assertThrows(EOFException.class, () -> input.read());
}
}
@Test
public void testMarkAndReset() throws Exception {
int position = 0;
final int readLimit = 10;
try (InputStream input = new TestNullInputStream(100, true, false)) {
assertTrue(input.markSupported(), "Mark Should be Supported");
// No Mark
final IOException noMarkException = assertThrows(IOException.class, input::reset);
assertEquals("No position has been marked", noMarkException.getMessage(), "No Mark IOException message");
for (; position < 3; position++) {
assertEquals(position, input.read(), "Read Before Mark [" + position + "]");
}
// Mark
input.mark(readLimit);
// Read further
for (int i = 0; i < 3; i++) {
assertEquals(position + i, input.read(), "Read After Mark [" + i + "]");
}
// Reset
input.reset();
// Read From marked position
for (int i = 0; i < readLimit + 1; i++) {
assertEquals(position + i, input.read(), "Read After Reset [" + i + "]");
}
// Reset after read limit passed
final IOException resetException = assertThrows(IOException.class, input::reset, "Read limit exceeded, expected IOException");
assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readLimit + "]", resetException.getMessage(),
"Read limit IOException message");
}
}
@Test
public void testMarkNotSupported() throws Exception {
final InputStream input = new TestNullInputStream(100, false, true);
assertFalse(input.markSupported(), "Mark Should NOT be Supported");
final UnsupportedOperationException markException = assertThrows(UnsupportedOperationException.class, () -> input.mark(5));
assertEquals(MARK_RESET_NOT_SUPPORTED, markException.getMessage(), "mark() error message");
final UnsupportedOperationException resetException = assertThrows(UnsupportedOperationException.class, input::reset);
assertEquals(MARK_RESET_NOT_SUPPORTED, resetException.getMessage(), "reset() error message");
input.close();
}
@Test
public void testRead() throws Exception {
final int size = 5;
final InputStream input = new TestNullInputStream(size);
for (int i = 0; i < size; i++) {
assertEquals(size - i, input.available(), "Check Size [" + i + "]");
assertEquals(i, input.read(), "Check Value [" + i + "]");
}
assertEquals(0, input.available(), "Available after contents all read");
// Check available is zero after End of file
assertEquals(-1, input.read(), "End of File");
assertEquals(0, input.available(), "Available after End of File");
// Test reading after the end of file
assertEquals(-1, input.read(), "End of File");
// Close - should reset
input.close();
assertEquals(size, input.available(), "Available after close");
}
@Test
public void testReadByteArray() throws Exception {
final byte[] bytes = new byte[10];
final InputStream input = new TestNullInputStream(15);
// Read into array
final int count1 = input.read(bytes);
assertEquals(bytes.length, count1, "Read 1");
for (int i = 0; i < count1; i++) {
assertEquals(i, bytes[i], "Check Bytes 1");
}
// Read into array
final int count2 = input.read(bytes);
assertEquals(5, count2, "Read 2");
for (int i = 0; i < count2; i++) {
assertEquals(count1 + i, bytes[i], "Check Bytes 2");
}
// End of File
final int count3 = input.read(bytes);
assertEquals(-1, count3, "Read 3 (EOF)");
// Test reading after the end of file
final int count4 = input.read(bytes);
assertEquals(-1, count4, "Read 4 (EOF)");
// reset by closing
input.close();
// Read into array using offset & length
final int offset = 2;
final int lth = 4;
final int count5 = input.read(bytes, offset, lth);
assertEquals(lth, count5, "Read 5");
for (int i = offset; i < lth; i++) {
assertEquals(i, bytes[i], "Check Bytes 2");
}
}
@Test
public void testReadByteArrayThrowAtEof() throws Exception {
final byte[] bytes = new byte[10];
final InputStream input = new TestNullInputStream(15, true, true);
// Read into array
final int count1 = input.read(bytes);
assertEquals(bytes.length, count1, "Read 1");
for (int i = 0; i < count1; i++) {
assertEquals(i, bytes[i], "Check Bytes 1");
}
// Read into array
final int count2 = input.read(bytes);
assertEquals(5, count2, "Read 2");
for (int i = 0; i < count2; i++) {
assertEquals(count1 + i, bytes[i], "Check Bytes 2");
}
// End of File
final IOException e1 = assertThrows(EOFException.class, () -> input.read(bytes));
assertTrue(StringUtils.isNotBlank(e1.getMessage()));
// Test reading after the end of file
final IOException e2 = assertThrows(EOFException.class, () -> input.read(bytes));
assertTrue(StringUtils.isNotBlank(e2.getMessage()));
// reset by closing
input.close();
// Read into array using offset & length
final int offset = 2;
final int lth = 4;
final int count5 = input.read(bytes, offset, lth);
assertEquals(lth, count5, "Read 5");
for (int i = offset; i < lth; i++) {
assertEquals(i, bytes[i], "Check Bytes 2");
}
}
@Test
public void testReadThrowAtEof() throws Exception {
final int size = 5;
final InputStream input = new TestNullInputStream(size, true, true);
for (int i = 0; i < size; i++) {
assertEquals(size - i, input.available(), "Check Size [" + i + "]");
assertEquals(i, input.read(), "Check Value [" + i + "]");
}
assertEquals(0, input.available(), "Available after contents all read");
// Check available is zero after End of file
final IOException e1 = assertThrows(EOFException.class, input::read);
assertTrue(StringUtils.isNotBlank(e1.getMessage()));
// Test reading after the end of file
final IOException e2 = assertThrows(EOFException.class, input::read);
assertTrue(StringUtils.isNotBlank(e2.getMessage()));
// Close - should reset
input.close();
assertEquals(size, input.available(), "Available after close");
}
@Test
public void testSkip() throws Exception {
try (InputStream input = new TestNullInputStream(10, true, false)) {
assertEquals(0, input.read(), "Read 1");
assertEquals(1, input.read(), "Read 2");
assertEquals(5, input.skip(5), "Skip 1");
assertEquals(7, input.read(), "Read 3");
assertEquals(2, input.skip(5), "Skip 2"); // only 2 left to skip
assertEquals(-1, input.skip(5), "Skip 3 (EOF)"); // End of file
assertEquals(-1, input.skip(5), "Skip 3 (EOF)"); // End of file
}
}
@Test
public void testSkipThrowAtEof() throws Exception {
try (InputStream input = new TestNullInputStream(10, true, true)) {
assertEquals(0, input.read(), "Read 1");
assertEquals(1, input.read(), "Read 2");
assertEquals(5, input.skip(5), "Skip 1");
assertEquals(7, input.read(), "Read 3");
assertEquals(2, input.skip(5), "Skip 2"); // only 2 left to skip
// End of File
final IOException e1 = assertThrows(EOFException.class, () -> input.skip(5), "Skip 3 (EOF)");
assertTrue(StringUtils.isNotBlank(e1.getMessage()));
final IOException e2 = assertThrows(IOException.class, () -> input.skip(5), "Expected IOException for skipping after end of file");
assertTrue(StringUtils.isNotBlank(e2.getMessage()));
}
}
}