/* * Copyright (c) 2008, Harald Kuhr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * * Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * 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 com.twelvemonkeys.io; import com.twelvemonkeys.lang.ObjectAbstractTest; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Random; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; /** * InputStreamAbstractTestCase *

* * @author Harald Kuhr * @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/test/java/com/twelvemonkeys/io/InputStreamAbstractTestCase.java#1 $ */ public abstract class InputStreamAbstractTest extends ObjectAbstractTest { // TODO: FixMe! THIS TEST IS (WAS) COMPLETELY BROKEN... // It relies on the contents of the stream being a certain order byte0 == 0, byte1 == 1 etc.. // But the subclasses don't implement this.. Need to fix. final static private long SEED = 29487982745l; final static Random sRandom = new Random(SEED); protected final Object makeObject() { return makeInputStream(); } protected InputStream makeInputStream() { return makeInputStream(16); } protected InputStream makeInputStream(int pSize) { byte[] bytes = makeRandomArray(pSize); return makeInputStream(bytes); } protected abstract InputStream makeInputStream(byte[] pBytes); protected final byte[] makeRandomArray(final int pSize) { byte[] bytes = new byte[pSize]; sRandom.nextBytes(bytes); return bytes; } protected final byte[] makeOrderedArray(final int pSize) { byte[] bytes = new byte[pSize]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) i; } return bytes; } @Test public void testRead() throws Exception { int size = 5; InputStream input = makeInputStream(makeOrderedArray(size)); for (int i = 0; i < size; i++) { assertTrue((size - i) >= input.available(), "Check Size [" + i + "]"); assertEquals(i, input.read(), "Check Value [" + i + "]"); } assertEquals(0, input.available(), "Available after contents all read"); // Test reading after the end of file try { int result = input.read(); assertEquals( -1, result, "Wrong value read after end of file"); } catch (IOException e) { fail("Should not have thrown an IOException: " + e.getMessage()); } } @Test public void testAvailable() throws Exception { InputStream input = makeInputStream(1); assertFalse(input.read() < 0, "Unexpected EOF"); assertEquals(0, input.available(), "Available after contents all read"); // Check availbale is zero after End of file assertEquals(-1, input.read(), "End of File"); assertEquals( 0, input.available(), "Available after End of File"); } @Test public void testReadByteArray() throws Exception { byte[] bytes = new byte[10]; byte[] data = makeOrderedArray(15); InputStream input = makeInputStream(data); // Read into array 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 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 int count3 = input.read(bytes); assertEquals(-1, count3, "Read 3 (EOF)"); // Test reading after the end of file try { int result = input.read(bytes); assertEquals(-1, result, "Wrong value read after end of file"); } catch (IOException e) { fail("Should not have thrown an IOException: " + e.getMessage()); } // Reset input = makeInputStream(data); // Read into array using offset & length int offset = 2; int lth = 4; int count5 = input.read(bytes, offset, lth); assertEquals(lth, count5, "Read 5"); for (int i = offset; i < lth; i++) { assertEquals(i - offset, bytes[i], "Check Bytes 2"); } } @Test public void testEOF() throws Exception { InputStream input = makeInputStream(makeOrderedArray(2)); assertEquals(0, input.read(), "Read 1"); assertEquals(1, input.read(), "Read 2"); assertEquals(-1, input.read(), "Read 3"); assertEquals(-1, input.read(), "Read 4"); assertEquals(-1, input.read(), "Read 5"); } @Test public void testMarkResetUnsupported() throws IOException { InputStream input = makeInputStream(10); if (input.markSupported()) { return; } input.mark(100); // Should be a no-op int read = input.read(); assertTrue(read >= 0); // TODO: According to InputStream#reset, it is allowed to do some // implementation specific reset, and still be correct... try { input.reset(); fail("Should throw IOException"); } catch (IOException e) { assertTrue(e.getMessage().contains("reset"), "Wrong messge: " + e.getMessage()); } } @Test public void testResetNoMark() throws Exception { InputStream input = makeInputStream(makeOrderedArray(10)); if (!input.markSupported()) { return; // Not supported, skip test } int read = input.read(); assertEquals(0, read); // No mark may either throw exception, or reset to beginning of stream. try { input.reset(); assertEquals(0, input.read(), "Re-read of reset data should be same"); } catch (Exception e) { assertTrue(e.getMessage().contains("mark"), "Wrong no mark IOException message"); } } @Test public void testMarkReset() throws Exception { InputStream input = makeInputStream(makeOrderedArray(25)); if (!input.markSupported()) { return; // Not supported, skip test } int read = input.read(); assertEquals(0, read); int position = 1; int readlimit = 10; // 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 + "]"); } } @Test public void testResetAfterReadLimit() throws Exception { InputStream input = makeInputStream(makeOrderedArray(25)); if (!input.markSupported()) { return; // Not supported, skip test } int read = input.read(); assertEquals(0, read); int position = 1; int readlimit = 5; // Mark input.mark(readlimit); // Read past marked position for (int i = 0; i < readlimit + 1; i++) { assertEquals((position + i), input.read(), "Read After Reset [" + i + "]"); } // Reset after read limit passed, may either throw exception, or reset to last mark try { input.reset(); assertEquals(1, input.read(), "Re-read of reset data should be same"); } catch (Exception e) { assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message"); } } @Test public void testResetAfterReset() throws Exception { InputStream input = makeInputStream(makeOrderedArray(25)); if (!input.markSupported()) { return; // Not supported, skip test } int first = input.read(); assertTrue(first >= 0, "Expected to read positive value"); int readlimit = 5; // Mark input.mark(readlimit); int read = input.read(); assertTrue(read >= 0, "Expected to read positive value"); assertTrue(input.read() >= 0); assertTrue(input.read() >= 0); input.reset(); assertEquals(read, input.read(), "Expected value read differs from actual"); // Reset after read limit passed, may either throw exception, or reset to last good mark try { input.reset(); int reRead = input.read(); assertTrue(reRead == read || reRead == first, "Re-read of reset data should be same as initially marked or first"); } catch (Exception e) { assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message"); } } @Test public void testSkip() throws Exception { InputStream input = makeInputStream(makeOrderedArray(10)); assertEquals(0, input.read(), "Unexpected value read"); assertEquals(1, input.read(), "Unexpected value read"); assertEquals(5, input.skip(5), "Unexpected number of bytes skipped"); assertEquals(7, input.read(), "Unexpected value read"); assertEquals(2, input.skip(5), "Unexpected number of bytes skipped"); // only 2 left to skip assertEquals(-1, input.read(), "Unexpected value read after EOF"); // Spec says skip might return 0 or negative after EOF... assertTrue(input.skip(5) <= 0, "Positive value skipped after EOF"); // End of file assertEquals(-1, input.read(), "Unexpected value read after EOF"); } @Test public void testSanityOrdered() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = makeOrderedArray(25); InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); for (byte b : bytes) { assertEquals((int) b, expected.read()); assertEquals((int) b, actual.read()); } } @Test public void testSanityOrdered2() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = makeOrderedArray(25); InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); byte[] e = new byte[bytes.length]; byte[] a = new byte[bytes.length]; assertEquals(e.length, expected.read(e, 0, e.length)); assertEquals(a.length, actual.read(a, 0, a.length)); for (int i = 0; i < bytes.length; i++) { assertEquals(bytes[i], e[i]); assertEquals(bytes[i], a[i]); } } @Test public void testSanityNegative() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = new byte[25]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) (255 - i); } InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); for (byte b : bytes) { assertEquals(b & 0xff, expected.read()); assertEquals(b & 0xff, actual.read()); } } @Test public void testSanityNegative2() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = new byte[25]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) (255 - i); } InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); byte[] e = new byte[bytes.length]; byte[] a = new byte[bytes.length]; assertEquals(e.length, expected.read(e, 0, e.length)); assertEquals(a.length, actual.read(a, 0, a.length)); for (int i = 0; i < bytes.length; i++) { assertEquals(bytes[i], e[i]); assertEquals(bytes[i], a[i]); } } @Test public void testSanityRandom() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = makeRandomArray(25); InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); for (byte b : bytes) { assertEquals(b & 0xff, expected.read()); assertEquals(b & 0xff, actual.read()); } } @Test public void testSanityRandom2() throws IOException { // This is to sanity check that the test itself is correct... byte[] bytes = makeRandomArray(25); InputStream expected = new ByteArrayInputStream(bytes); InputStream actual = makeInputStream(bytes); byte[] e = new byte[bytes.length]; byte[] a = new byte[bytes.length]; assertEquals(e.length, expected.read(e, 0, e.length)); assertEquals(a.length, actual.read(a, 0, a.length)); for (int i = 0; i < bytes.length; i++) { assertEquals(bytes[i], e[i]); assertEquals(bytes[i], a[i]); } }}