/* * $Id$ * * Copyright 2006, The jCoderZ.org Project. 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 jCoderZ.org Project 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 REGENTS 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 REGENTS AND 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. */ package org.jcoderz.commons.util; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.Reader; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.channels.Channel; import java.nio.channels.ReadableByteChannel; import java.util.Arrays; import java.util.Random; import junit.framework.TestCase; /** * Unit Tests for the class {@link org.jcoderz.commons.util.IoUtil}. * * @author Michael Griffel */ public class IoUtilTest extends TestCase { private static final Random RANDOM_GENERATOR = new Random(); private static final int GAP_SIZE = 10 * 1024; /** * Tests the method {@link IoUtil#readFully(InputStream, int)}. * @throws IOException in case of an unexpected I/O error. */ public void testReadFully () throws IOException { read1kBytes(); read0Bytes(); readAhead(); underread(); } /** * Tests the method {@link IoUtil#close(InputStream)}. */ public void testSafeCloseInputStream () { final InputStream in = new ByteArrayInputStream(new byte[0]) { public void close () throws IOException { throw new IOException(); } }; IoUtil.close(in); IoUtil.close(in); IoUtil.close((InputStream) null); } /** * Tests the method {@link IoUtil#close(OutputStream)}. */ public void testSafeCloseOutputStream () { final OutputStream out = new ByteArrayOutputStream() { public void close () throws IOException { throw new IOException(); } }; IoUtil.close(out); IoUtil.close(out); IoUtil.close((OutputStream) null); } /** * Tests the method {@link IoUtil#close(Reader)}. */ public void testSafeCloseReader () { final Reader reader = new Reader() { public void close () throws IOException { throw new IOException(); } public int read (char[] cbuf, int off, int len) { return 0; } }; IoUtil.close(reader); IoUtil.close(reader); IoUtil.close((Reader) null); } /** * Tests the method {@link IoUtil#close(Writer)}. */ public void testSafeCloseWriter () { final Writer writer = new Writer() { public void close () throws IOException { throw new IOException(); } public void flush () { // NOP } public void write (char[] cbuf, int off, int len) { // NOP } }; IoUtil.close(writer); IoUtil.close(writer); IoUtil.close((Writer) null); } /** * Tests the method {@link IoUtil#close(RandomAccessFile)}. * @throws Exception in case of an unexpected error. */ public void testSafeCloseRandomAccessFile () throws Exception { final File tmp = File.createTempFile("tmp", "tmp"); tmp.deleteOnExit(); final RandomAccessFile file = new RandomAccessFile(tmp, "r") { public void close () throws IOException { throw new IOException(); } }; IoUtil.close(file); IoUtil.close(file); IoUtil.close((RandomAccessFile) null); } /** * Tests the method {@link IoUtil#close(Channel)}. * @throws Exception in case of an unexpected error. */ public void testSafeCloseChannel () throws Exception { final Channel channel = new ChannelImpl(); IoUtil.close(channel); IoUtil.close(channel); IoUtil.close((Channel) null); } public void testSkip() throws Exception { final File tmp = File.createTempFile("fawkez", "tmp"); FileOutputStream out = new FileOutputStream(tmp); out.write(1); out.write(new byte[GAP_SIZE]); out.write(2); out.close(); final InputStream in = new BufferedInputStream(new FileInputStream((tmp))); int first = in.read(); IoUtil.skip(in, GAP_SIZE); // instead of in.skip(GAP_SIZE); int second = in.read(); assertEquals(3, first + second); } private void read1kBytes () throws IOException { final byte[] inData = new byte[Constants.BYTES_PER_KILO_BYTE]; final InputStream in = createRandomInputStream(inData); final byte[] outData = IoUtil.readFully(in, inData.length); assertTrue("bytes arrays should be equal", Arrays.equals(inData, outData)); } private void read0Bytes () throws IOException { final byte[] inData = new byte[0]; final InputStream in = createRandomInputStream(inData); final byte[] outData = IoUtil.readFully(in, inData.length); assertTrue("bytes arrays should be equal", Arrays.equals(inData, outData)); } private void readAhead () { final byte[] inData = new byte[Constants.BYTES_PER_KILO_BYTE]; final InputStream in = createRandomInputStream(inData); try { IoUtil.readFully(in, inData.length + 1); fail("Expected IOException for reading more bytes than available"); } catch (IOException expected) { assertNotNull("Expected a real exception.", expected); } } private void underread () throws IOException { final byte[] inData = new byte[Constants.BYTES_PER_KILO_BYTE]; final InputStream in = createRandomInputStream(inData); final byte[] outData = IoUtil.readFully(in, inData.length - 1); final byte[] strippedInData = new byte[inData.length - 1]; System.arraycopy(inData, 0, strippedInData, 0, inData.length - 1); assertTrue("bytes arrays should be equal except the last one", Arrays.equals(strippedInData, outData)); } private InputStream createRandomInputStream (byte[] inData) { RANDOM_GENERATOR.nextBytes(inData); final InputStream in = new ByteArrayInputStream(inData); return in; } private static final class ChannelImpl implements ReadableByteChannel { private boolean mIsOpen = true; /** {@inheritDoc} */ public int read (ByteBuffer dst) { return 0; } /** {@inheritDoc} */ public void close () throws IOException { if (mIsOpen) { mIsOpen = false; } else { throw new IOException(); } } /** {@inheritDoc} */ public boolean isOpen () { return mIsOpen; } } }