commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nia...@apache.org
Subject svn commit: r454222 - in /jakarta/commons/proper/io/trunk/src: java/org/apache/commons/io/input/MockInputStream.java test/org/apache/commons/io/input/MockInputStreamTestCase.java
Date Sun, 08 Oct 2006 22:09:29 GMT
Author: niallp
Date: Sun Oct  8 15:09:28 2006
New Revision: 454222

URL: http://svn.apache.org/viewvc?view=rev&rev=454222
Log:
IO-94 - add new MockInputStream

Added:
    jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
  (with props)
    jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
  (with props)

Added: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java?view=auto&rev=454222
==============================================================================
--- jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
(added)
+++ jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
Sun Oct  8 15:09:28 2006
@@ -0,0 +1,309 @@
+/*
+ * 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 java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A mock {@link InputStream} for testing purposes.
+ * <p>
+ * This implementation provides a light weight mock
+ * object for testing with an {@link InputStream}
+ * where the contents don't matter.
+ * <p>
+ * One use case would be for testing the handling of
+ * large {@link InputStream} as it can emulate that
+ * scenario without the overhead of actually processing
+ * large numbers of bytes - significantly speeding up
+ * test execution times.
+ * <p>
+ * Alternatively, if some kind of data is required as part
+ * of a test the <code>processByte()</code> and
+ * <code>processBytes()</code> methods can be implemented to generate
+ * test data.
+ *
+ *
+ * @since Commons IO 1.3
+ * @version $Revision$
+ */
+public class MockInputStream extends InputStream {
+
+    private long size;
+    private long position;
+    private long mark = -1;
+    private long readlimit;
+    private boolean eof;
+    private boolean throwEofException;
+    private boolean markSupported;
+
+    /**
+     * Create a mock {@link InputStream} of the specified size.
+     *
+     * @param size The size of the mock input stream.
+     */
+    public MockInputStream(long size) {
+       this(size, true, false);
+    }
+
+    /**
+     * Create a mock {@link InputStream} of the specified
+     * size and option settings.
+     *
+     * @param size The size of the mock input stream.
+     * @param markSupported Whether this instance will support
+     * the <code>mark()</code> functionality.
+     * @param throwEofException Whether this implementation
+     * will throw an {@link EOFException} or return -1 when the
+     * end of file is reached.
+     */
+    public MockInputStream(long size, boolean markSupported, boolean throwEofException) {
+       this.size = size;
+       this.markSupported = markSupported;
+       this.throwEofException = throwEofException;
+    }
+
+    /**
+     * Return the current position.
+     *
+     * @return the current position.
+     */
+    public long getPosition() {
+        return position;
+    }
+
+    /**
+     * Return the size of this Mock {@link InputStream}
+     *
+     * @return the size of the mock input stream.
+     */
+    public long getSize() {
+        return size;
+    }
+
+    /**
+     * Return the number of bytes that can be read.
+     *
+     * @return The number of bytes that can be read.
+     */
+    public int available() {
+        long avail = size - position;
+        if (avail <= 0) {
+            return 0;
+        } else if (avail > Integer.MAX_VALUE) {
+            return Integer.MAX_VALUE;
+        } else {
+            return (int)avail;
+        }
+    }
+
+    /**
+     * Close this inputstream - resets the internal state to
+     * the initial values.
+     *
+     * @throws IOException If an error occurs.
+     */
+    public void close() throws IOException {
+        eof = false;
+        position = 0;
+        mark = -1;
+    }
+
+    /**
+     * Mark the current position.
+     *
+     * @param readlimit The number of bytes before this marked position
+     * is invalid.
+     * @throws UnsupportedOperationException if mark is not supported.
+     */
+    public synchronized void mark(int readlimit) {
+        if (!markSupported) {
+            throw new UnsupportedOperationException("Mark not supported");
+        }
+        mark = position;
+        this.readlimit = readlimit;
+    }
+
+    /**
+     * Indicates whether <i>mark</i> is supported.
+     *
+     * @return Whether <i>mark</i> is supported or not.
+     */
+    public boolean markSupported() {
+        return markSupported;
+    }
+
+    /**
+     * Read a byte.
+     *
+     * @return Either The byte value returned by <code>readValue()</code>
+     * or <code>-1</code> if the end of file has been reached and
+     * <code>throwEofException</code> is set to <code>false</code>.
+     * @throws EOFException if the end of file is reached and
+     * <code>throwEofException</code> is set to <code>true</code>.
+     * @throws IOException if trying to read past the end of file.
+     */
+    public int read() throws IOException {
+        if (eof) {
+            throw new IOException("Read after end of file");
+        }
+        if (position == size) {
+            return doEndOfFile();
+        }
+        position++;
+        return processByte();
+    }
+
+    /**
+     * Read some bytes into the specified array.
+     *
+     * @param bytes The byte array to read into
+     * @return The number of bytes read or <code>-1</code>
+     * if the end of file has been reached and
+     * <code>throwEofException</code> is set to <code>false</code>.
+     * @throws EOFException if the end of file is reached and
+     * <code>throwEofException</code> is set to <code>true</code>.
+     * @throws IOException if trying to read past the end of file.
+     */
+    public int read(byte[] bytes) throws IOException {
+        return read(bytes, 0, bytes.length);
+    }
+
+    /**
+     * Read the specified number bytes into an array.
+     *
+     * @param bytes The byte array to read into.
+     * @param offset The offset to start reading bytes into.
+     * @param length The number of bytes to read.
+     * @return The number of bytes read or <code>-1</code>
+     * if the end of file has been reached and
+     * <code>throwEofException</code> is set to <code>false</code>.
+     * @throws EOFException if the end of file is reached and
+     * <code>throwEofException</code> is set to <code>true</code>.
+     * @throws IOException if trying to read past the end of file.
+     */
+    public int read(byte[] bytes, int offset, int length) throws IOException {
+        if (eof) {
+            throw new IOException("Read after end of file");
+        }
+        if (position == size) {
+            return doEndOfFile();
+        }
+        position += length;
+        int returnLength = length;
+        if (position > size) {
+            returnLength = length - (int)(position - size);
+            position = size;
+        }
+        processBytes(bytes, offset, returnLength);
+        return returnLength;
+    }
+
+    /**
+     * Reset the stream to the point when mark was last called.
+     *
+     * @throws UnsupportedOperationException if mark is not supported.
+     * @throws IOException If no position has been marked
+     * or the read limit has been exceed since the last position was
+     * marked.
+     */
+    public synchronized void reset() throws IOException {
+        if (!markSupported) {
+            throw new UnsupportedOperationException("Mark not supported");
+        }
+        if (mark < 0) {
+            throw new IOException("No position has been marked");
+        }
+        if (position > (mark + readlimit)) {
+            throw new IOException("Marked position [" + mark +
+                    "] is no longer valid - passed the read limit [" +
+                    readlimit + "]");
+        }
+        position = mark;
+        eof = false;
+    }
+
+    /**
+     * Skip a specified number of bytes.
+     *
+     * @param numberOfBytes The number of bytes to skip.
+     * @return The number of bytes skipped or <code>-1</code>
+     * if the end of file has been reached and
+     * <code>throwEofException</code> is set to <code>false</code>.
+     * @throws EOFException if the end of file is reached and
+     * <code>throwEofException</code> is set to <code>true</code>.
+     * @throws IOException if trying to read past the end of file.
+     */
+    public long skip(long numberOfBytes) throws IOException {
+        if (eof) {
+            throw new IOException("Skip after end of file");
+        }
+        if (position == size) {
+            return doEndOfFile();
+        }
+        position += numberOfBytes;
+        long returnLength = numberOfBytes;
+        if (position > size) {
+            returnLength = numberOfBytes - (position - size);
+            position = size;
+        }
+        return returnLength;
+    }
+
+    /**
+     * Return a byte value for the  <code>read()</code> method.
+     * <p>
+     * <strong>N.B.</strong> This implementation returns
+     * zero.
+     *
+     * @return This implementation always returns zero.
+     */
+    protected int processByte() {
+        return 0;
+    }
+
+    /**
+     * Process the bytes for the <code>read(byte[], offset, length)</code>
+     * method.
+     * <p>
+     * <strong>N.B.</strong> This implementation leaves the byte
+     * array unchanged.
+     *
+     * @param bytes The byte array
+     * @param offset The offset to start at.
+     * @param length The number of bytes.
+     */
+    protected void processBytes(byte[] bytes, int offset, int length) {
+    }
+
+    /**
+     * Handle End of File.
+     *
+     * @return <code>-1</code> if <code>throwEofException</code>
is
+     * set to <code>false</code>
+     * @throws EOFException if <code>throwEofException</code> is set
+     * to <code>true</code>.
+     */
+    private int doEndOfFile() throws EOFException {
+        eof = true;
+        if (throwEofException) {
+            throw new EOFException();
+        }
+        return -1;
+    }
+}

Propchange: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/input/MockInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java?view=auto&rev=454222
==============================================================================
--- jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
(added)
+++ jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
Sun Oct  8 15:09:28 2006
@@ -0,0 +1,256 @@
+/*
+ * 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 java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * JUnit Test Case for {@link MockInputStream}.
+ *
+ * @version $Id$
+ */
+public class MockInputStreamTestCase extends TestCase {
+
+    /** Constructor */
+    public MockInputStreamTestCase(String name) {
+        super(name);
+    }
+
+    /** Set up */
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    /** Tear Down */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test <code>available()</code> method.
+     */
+    public void testRead() throws Exception {
+        int size = 5;
+        InputStream input = new TestMockInputStream(size);
+        for (int i = 0; i < size; i++) {
+            assertEquals("Check Size [" + i + "]", (size - i), input.available());
+            assertEquals("Check Value [" + i + "]", i, input.read());
+        }
+        assertEquals("Available after contents all read", 0, input.available());
+
+        // Check availbale is zero after End of file
+        assertEquals("End of File", -1, input.read());
+        assertEquals("Available after End of File", 0, input.available());
+
+        // Test reading after the end of file
+        try {
+            int result = input.read();
+            fail("Should have thrown an IOException, byte=[" + result + "]");
+        } catch (IOException e) {
+            assertEquals("Read after end of file", e.getMessage());
+        }
+
+        // Close - should reset
+        input.close();
+        assertEquals("Available after close", size, input.available());
+    }
+
+    /**
+     * Test <code>read(byte[])</code> method.
+     */
+    public void testReadByteArray() throws Exception {
+        byte[] bytes = new byte[10];
+        InputStream input = new TestMockInputStream(15);
+
+        // Read into array
+        int count1 = input.read(bytes);
+        assertEquals("Read 1", bytes.length, count1);
+        for (int i = 0; i < count1; i++) {
+            assertEquals("Check Bytes 1", i, bytes[i]);
+        }
+
+        // Read into array
+        int count2 = input.read(bytes);
+        assertEquals("Read 2", 5, count2);
+        for (int i = 0; i < count2; i++) {
+            assertEquals("Check Bytes 2", count1 + i, bytes[i]);
+        }
+
+        // End of File
+        int count3 = input.read(bytes);
+        assertEquals("Read 3 (EOF)", -1, count3);
+
+        // Test reading after the end of file
+        try {
+            int count4 = input.read(bytes);
+            fail("Should have thrown an IOException, byte=[" + count4 + "]");
+        } catch (IOException e) {
+            assertEquals("Read after end of file", e.getMessage());
+        }
+
+        // reset by closing
+        input.close();
+    
+        // Read into array using offset & length
+        int offset = 2;
+        int lth    = 4;
+        int count5 = input.read(bytes, offset, lth);
+        assertEquals("Read 5", lth, count5);
+        for (int i = offset; i < lth; i++) {
+            assertEquals("Check Bytes 2", i, bytes[i]);
+        }
+    }
+
+    /**
+     * Test when configured to throw an EOFException at the end of file
+     * (rather than return -1).
+     */
+    public void testEOFException() throws Exception {
+        InputStream input = new TestMockInputStream(2, false, true);
+        assertEquals("Read 1",  0, input.read());
+        assertEquals("Read 2",  1, input.read());
+        try {
+            int result = input.read();
+            fail("Should have thrown an EOFException, byte=[" + result + "]");
+        } catch (EOFException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Test <code>mark()</code> and <code>reset()</code> methods.
+     */
+    public void testMarkAndReset() throws Exception {
+        int position = 0;
+        int readlimit = 10;
+        InputStream input = new TestMockInputStream(100, true, false);
+        
+        assertTrue("Mark Should be Supported", input.markSupported());
+
+        // No Mark
+        try {
+            input.reset();
+            fail("Read limit exceeded, expected IOException ");
+        } catch (Exception e) {
+            assertEquals("No Mark IOException message",
+                         "No position has been marked",
+                         e.getMessage());
+        }
+
+        for (; position < 3; position++) {
+            assertEquals("Read Before Mark [" + position +"]",  position, input.read());
+        }
+
+        // Mark
+        input.mark(readlimit);
+
+        // Read further
+        for (int i = 0; i < 3; i++) {
+            assertEquals("Read After Mark [" + i +"]",  (position + i), input.read());
+        }
+
+        // Reset
+        input.reset();
+
+        // Read From marked position
+        for (int i = 0; i < readlimit + 1; i++) {
+            assertEquals("Read After Reset [" + i +"]",  (position + i), input.read());
+        }
+
+        // Reset after read limit passed
+        try {
+            input.reset();
+            fail("Read limit exceeded, expected IOException ");
+        } catch (Exception e) {
+            assertEquals("Read limit IOException message",
+                         "Marked position [" + position
+                         + "] is no longer valid - passed the read limit ["
+                         + readlimit + "]",
+                         e.getMessage());
+        }
+    }
+
+    /**
+     * Test <code>mark()</code> not supported.
+     */
+    public void testMarkNotSupported() throws Exception {
+        InputStream input = new TestMockInputStream(100, false, true);
+        assertFalse("Mark Should NOT be Supported", input.markSupported());
+
+        try {
+            input.mark(5);
+            fail("mark() should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("mark() error message",  "Mark not supported", e.getMessage());
+        }
+
+        try {
+            input.reset();
+            fail("reset() should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            assertEquals("reset() error message",  "Mark not supported", e.getMessage());
+        }
+    }
+
+    /**
+     * Test <code>skip()</code> method.
+     */
+   public void testSkip() throws Exception {
+        int skip = 20;
+        InputStream input = new TestMockInputStream(10, true, false);
+        assertEquals("Read 1", 0, input.read());
+        assertEquals("Read 2", 1, input.read());
+        assertEquals("Skip 1", 5, input.skip(5));
+        assertEquals("Read 3", 7, input.read());
+        assertEquals("Skip 2", 2, input.skip(5)); // only 2 left to skip
+        assertEquals("Skip 3 (EOF)", -1, input.skip(5)); // End of file
+        try {
+            input.skip(5); //
+            fail("Expected IOException for skipping after end of file");
+        } catch (Exception e) {
+            assertEquals("Skip after EOF IOException message",
+                    "Skip after end of file",
+                    e.getMessage());
+        }
+    }
+
+
+    // ------------- Test MockInputStream implementation -------------
+
+    private static final class TestMockInputStream extends MockInputStream {
+        public TestMockInputStream(int size) {
+            super(size);
+        }
+        public TestMockInputStream(int size, boolean markSupported, boolean throwEofException)
{
+            super(size, markSupported, throwEofException);
+        }
+        protected int processByte() {
+            return ((int)getPosition() - 1);
+        }
+        protected void processBytes(byte[] bytes, int offset, int length) {
+            int startPos = (int)getPosition() - length;
+            for (int i = offset; i < length; i++) {
+                bytes[i] = (byte)(startPos + i);
+            }
+        }
+        
+    }
+}

Propchange: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/input/MockInputStreamTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message