Sean Qiu wrote: > Oops, since this JIRA is assigned to me, and I've found no objection there.I > thought you are polite to wait for me to commit it. (Obviously, I was > wrong. :-) > > +1 for the Tim proposed (which is committed by me) patch. > If anyone has any other thoughts, I can revert it back.
The problem is that that the patch I uploaded is not complete. It was there for discussion about the direction I was taking. To complete it will require a new lock to avoid a race when closing the stream and refilling it on different threads. All these changes /may/ be worse than using a synchronized close. Regards, Tim > 2008/11/28 Tim Ellison <[EMAIL PROTECTED]> > >> Hmm, I'm surprised that you committed my patch Sean -- I could have done >> it myself if I'd thought we were done with the discussion. >> >> So did we conclude that the problems inherent in this version are any >> better than the problems in the original version? >> >> In summary, >> - the original code synchronized on close(), unlike the RI. Its safe, >> but can cause potential deadlock if people rely on the unspecified RI >> behavior. >> - the proposed (erm, committed ;-) patch is unsynchronized, but now has >> a race condition (see the FIXME comment) which could miss the close. >> >> Regards, >> Tim >> >> [EMAIL PROTECTED] wrote: >>> Author: qiuxx >>> Date: Wed Nov 26 19:24:37 2008 >>> New Revision: 721075 >>> >>> URL: http://svn.apache.org/viewvc?rev=721075&view=rev >>> Log: >>> Apply for HARMONY-6014,([classlib][luni] BufferedInputStream can not be >> closed in another thread) >>> Modified: >>> >> harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedInputStream.java >> harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedInputStreamTest.java >>> Modified: >> harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedInputStream.java >>> URL: >> http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedInputStream.java?rev=721075&r1=721074&r2=721075&view=diff >> ============================================================================== >>> --- >> harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedInputStream.java >> (original) >>> +++ >> harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedInputStream.java >> Wed Nov 26 19:24:37 2008 >>> @@ -21,8 +21,8 @@ >>> >>> /** >>> * <code>BufferedInputStream</code> is a class which takes an input >> stream and >>> - * <em>buffers</em> the input. In this way, costly interaction with the >>> - * original input stream can be minimized by reading buffered amounts of >> data >>> + * <em>buffers</em> the input. In this way, costly interaction with the >> original >>> + * input stream can be minimized by reading buffered amounts of data >>> * infrequently. The drawback is that extra space is required to hold >> the buffer >>> * and that copying takes place when reading that buffer. >>> * >>> @@ -32,7 +32,7 @@ >>> /** >>> * The buffer containing the current bytes read from the target >> InputStream. >>> */ >>> - protected byte[] buf; >>> + protected volatile byte[] buf; >>> >>> /** >>> * The total number of bytes inside the byte array <code>buf</code>. >>> @@ -55,12 +55,10 @@ >>> */ >>> protected int pos; >>> >>> - private boolean closed = false; >>> - >>> /** >>> * Constructs a new <code>BufferedInputStream</code> on the >> InputStream >>> - * <code>in</code>. The default buffer size (8Kb) is allocated and >> all >>> - * reads can now be filtered through this stream. >>> + * <code>in</code>. The default buffer size (8Kb) is allocated and >> all reads >>> + * can now be filtered through this stream. >>> * >>> * @param in >>> * the InputStream to buffer reads on. >>> @@ -101,11 +99,12 @@ >>> */ >>> @Override >>> public synchronized int available() throws IOException { >>> - if (buf == null) { >>> + InputStream localIn = in; // 'in' could be invalidated by >> close() >>> + if (buf == null || localIn == null) { >>> // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> - return count - pos + in.available(); >>> + return count - pos + localIn.available(); >>> } >>> >>> /** >>> @@ -116,19 +115,20 @@ >>> * If an error occurs attempting to close this stream. >>> */ >>> @Override >>> - public synchronized void close() throws IOException { >>> - if (null != in) { >>> - super.close(); >>> - in = null; >>> - } >>> + public void close() throws IOException { >>> buf = null; >>> - closed = true; >>> + InputStream localIn = in; >>> + in = null; >>> + if (localIn != null) { >>> + localIn.close(); >>> + } >>> } >>> >>> - private int fillbuf() throws IOException { >>> + private int fillbuf(InputStream localIn, byte[] localBuf) >>> + throws IOException { >>> if (markpos == -1 || (pos - markpos >= marklimit)) { >>> /* Mark position not set or exceeded readlimit */ >>> - int result = in.read(buf); >>> + int result = localIn.read(localBuf); >>> if (result > 0) { >>> markpos = -1; >>> pos = 0; >>> @@ -136,32 +136,35 @@ >>> } >>> return result; >>> } >>> - if (markpos == 0 && marklimit > buf.length) { >>> - /* Increase buffer size to accomodate the readlimit */ >>> - int newLength = buf.length * 2; >>> + if (markpos == 0 && marklimit > localBuf.length) { >>> + /* Increase buffer size to accommodate the readlimit */ >>> + int newLength = localBuf.length * 2; >>> if (newLength > marklimit) { >>> newLength = marklimit; >>> } >>> byte[] newbuf = new byte[newLength]; >>> - System.arraycopy(buf, 0, newbuf, 0, buf.length); >>> - buf = newbuf; >>> + System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length); >>> + // Reassign buf, which will invalidate any local references >>> + // FIXME: what if buf was null? >>> + localBuf = buf = newbuf; >>> } else if (markpos > 0) { >>> - System.arraycopy(buf, markpos, buf, 0, buf.length - >> markpos); >>> + System.arraycopy(localBuf, markpos, localBuf, 0, >> localBuf.length >>> + - markpos); >>> } >>> /* Set the new position and mark position */ >>> pos -= markpos; >>> count = markpos = 0; >>> - int bytesread = in.read(buf, pos, buf.length - pos); >>> + int bytesread = localIn.read(localBuf, pos, localBuf.length - >> pos); >>> count = bytesread <= 0 ? pos : pos + bytesread; >>> return bytesread; >>> } >>> >>> /** >>> * Set a Mark position in this BufferedInputStream. The parameter >>> - * <code>readLimit</code> indicates how many bytes can be read >> before a >>> - * mark is invalidated. Sending reset() will reposition the Stream >> back to >>> - * the marked position provided <code>readLimit</code> has not been >>> - * surpassed. The underlying buffer may be increased in size to >> allow >>> + * <code>readLimit</code> indicates how many bytes can be read >> before a mark >>> + * is invalidated. Sending reset() will reposition the Stream back >> to the >>> + * marked position provided <code>readLimit</code> has not been >> surpassed. >>> + * The underlying buffer may be increased in size to allow >>> * <code>readlimit</code> number of bytes to be supported. >>> * >>> * @param readlimit >>> @@ -200,28 +203,40 @@ >>> */ >>> @Override >>> public synchronized int read() throws IOException { >>> - if (in == null) { >>> + // Use local refs since buf and in may be invalidated by an >>> + // unsynchronized close() >>> + byte[] localBuf = buf; >>> + InputStream localIn = in; >>> + if (localBuf == null || localIn == null) { >>> // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> >>> /* Are there buffered bytes available? */ >>> - if (pos >= count && fillbuf() == -1) { >>> + if (pos >= count && fillbuf(localIn, localBuf) == -1) { >>> return -1; /* no, fill buffer */ >>> } >>> + // localBuf may have been invalidated by fillbuf >>> + if (localBuf != buf) { >>> + localBuf = buf; >>> + if (localBuf == null) { >>> + // K0059=Stream is closed >>> + throw new IOException(Msg.getString("K0059")); >> //$NON-NLS-1$ >>> + } >>> + } >>> >>> /* Did filling the buffer fail with -1 (EOF)? */ >>> if (count - pos > 0) { >>> - return buf[pos++] & 0xFF; >>> + return localBuf[pos++] & 0xFF; >>> } >>> return -1; >>> } >>> >>> /** >>> - * Reads at most <code>length</code> bytes from this >> BufferedInputStream >>> - * and stores them in byte array <code>buffer</code> starting at >> offset >>> - * <code>offset</code>. Answer the number of bytes actually read or >> -1 if >>> - * no bytes were read and end of stream was encountered. If all the >> buffered >>> + * Reads at most <code>length</code> bytes from this >> BufferedInputStream and >>> + * stores them in byte array <code>buffer</code> starting at offset >>> + * <code>offset</code>. Answer the number of bytes actually read or >> -1 if no >>> + * bytes were read and end of stream was encountered. If all the >> buffered >>> * bytes have been used, a mark has not been set, and the requested >> number >>> * of bytes is larger than the receiver's buffer size, this >> implementation >>> * bypasses the buffer and simply places the results directly into >>> @@ -242,7 +257,10 @@ >>> @Override >>> public synchronized int read(byte[] buffer, int offset, int length) >>> throws IOException { >>> - if (closed) { >>> + // Use local ref since buf may be invalidated by an >> unsynchronized >>> + // close() >>> + byte[] localBuf = buf; >>> + if (localBuf == null) { >>> // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> @@ -253,7 +271,9 @@ >>> if (length == 0) { >>> return 0; >>> } >>> - if (null == buf) { >>> + InputStream localIn = in; >>> + if (localIn == null) { >>> + // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> >>> @@ -261,9 +281,9 @@ >>> if (pos < count) { >>> /* There are bytes available in the buffer. */ >>> int copylength = count - pos >= length ? length : count - >> pos; >>> - System.arraycopy(buf, pos, buffer, offset, copylength); >>> + System.arraycopy(localBuf, pos, buffer, offset, copylength); >>> pos += copylength; >>> - if (copylength == length || in.available() == 0) { >>> + if (copylength == length || localIn.available() == 0) { >>> return copylength; >>> } >>> offset += copylength; >>> @@ -278,24 +298,33 @@ >>> * If we're not marked and the required size is greater than >> the >>> * buffer, simply read the bytes directly bypassing the >> buffer. >>> */ >>> - if (markpos == -1 && required >= buf.length) { >>> - read = in.read(buffer, offset, required); >>> + if (markpos == -1 && required >= localBuf.length) { >>> + read = localIn.read(buffer, offset, required); >>> if (read == -1) { >>> return required == length ? -1 : length - required; >>> } >>> } else { >>> - if (fillbuf() == -1) { >>> + if (fillbuf(localIn, localBuf) == -1) { >>> return required == length ? -1 : length - required; >>> } >>> + // localBuf may have been invalidated by fillbuf >>> + if (localBuf != buf) { >>> + localBuf = buf; >>> + if (localBuf == null) { >>> + // K0059=Stream is closed >>> + throw new IOException(Msg.getString("K0059")); >> //$NON-NLS-1$ >>> + } >>> + } >>> + >>> read = count - pos >= required ? required : count - pos; >>> - System.arraycopy(buf, pos, buffer, offset, read); >>> + System.arraycopy(localBuf, pos, buffer, offset, read); >>> pos += read; >>> } >>> required -= read; >>> if (required == 0) { >>> return length; >>> } >>> - if (in.available() == 0) { >>> + if (localIn.available() == 0) { >>> return length - required; >>> } >>> offset += read; >>> @@ -304,18 +333,16 @@ >>> >>> /** >>> * Reset this BufferedInputStream to the last marked location. If >> the >>> - * <code>readlimit</code> has been passed or no <code>mark</code> >> has >>> - * been set, throw IOException. This implementation resets the >> target >>> - * stream. >>> + * <code>readlimit</code> has been passed or no <code>mark</code> >> has been >>> + * set, throw IOException. This implementation resets the target >> stream. >>> * >>> * @throws IOException >>> * If the stream is already closed or another >> IOException >>> * occurs. >>> */ >>> - >>> @Override >>> public synchronized void reset() throws IOException { >>> - if (closed) { >>> + if (buf == null) { >>> // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> @@ -341,7 +368,11 @@ >>> */ >>> @Override >>> public synchronized long skip(long amount) throws IOException { >>> - if (null == in) { >>> + // Use local refs since buf and in may be invalidated by an >>> + // unsynchronized close() >>> + byte[] localBuf = buf; >>> + InputStream localIn = in; >>> + if (localBuf == null || localIn == null) { >>> // K0059=Stream is closed >>> throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ >>> } >>> @@ -358,7 +389,7 @@ >>> >>> if (markpos != -1) { >>> if (amount <= marklimit) { >>> - if (fillbuf() == -1) { >>> + if (fillbuf(localIn, localBuf) == -1) { >>> return read; >>> } >>> if (count - pos >= amount - read) { >>> @@ -372,6 +403,6 @@ >>> } >>> markpos = -1; >>> } >>> - return read + in.skip(amount - read); >>> + return read + localIn.skip(amount - read); >>> } >>> } >>> >>> Modified: >> harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedInputStreamTest.java >>> URL: >> http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedInputStreamTest.java?rev=721075&r1=721074&r2=721075&view=diff >> ============================================================================== >>> --- >> harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedInputStreamTest.java >> (original) >>> +++ >> harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedInputStreamTest.java >> Wed Nov 26 19:24:37 2008 >>> @@ -1,443 +1,489 @@ >>> -/* >>> - * 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.harmony.luni.tests.java.io; >>> - >>> -import java.io.BufferedInputStream; >>> -import java.io.ByteArrayInputStream; >>> -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 junit.framework.TestCase; >>> -import tests.support.Support_PlatformFile; >>> - >>> -public class BufferedInputStreamTest extends TestCase { >>> - >>> - public String fileName; >>> - >>> - private BufferedInputStream is; >>> - >>> - private FileInputStream isFile; >>> - >>> - byte[] ibuf = new byte[4096]; >>> - >>> - public String fileString = >> "Test_All_Tests\nTest_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\nTest_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\nTest_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\nTest_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\nTest_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\nTest_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\nTest_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang >> _Cl >> >> assNotFoundException\nTest_java_lang_CloneNotSupportedException\nTest_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\nTest_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\nTest_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\nTest_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\nTest_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\nTest_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\nTest_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\nTest_java_l a >> ng_ >> >> Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\nTest_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\nTest_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\nTest_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\nTest_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\nTest_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\nTest_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\nTest_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_ S >> ock >> >> etException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\nTest_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\nTest_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\nTest_java_util_tm\nTest_java_util_Vector\n"; >>> - >>> - /* >>> - * @tests java.io.BufferedInputStream(InputStream) >>> - */ >>> - public void test_ConstructorLjava_io_InputStream() { >>> - try { >>> - BufferedInputStream str = new BufferedInputStream(null); >>> - str.read(); >>> - fail("Expected an IOException"); >>> - } catch (IOException e) { >>> - // Expected >>> - } >>> - } >>> - >>> - /* >>> - * @tests java.io.BufferedInputStream(InputStream) >>> - */ >>> - public void test_ConstructorLjava_io_InputStreamI() throws >> IOException { >>> - try { >>> - BufferedInputStream str = new BufferedInputStream(null, 1); >>> - str.read(); >>> - fail("Expected an IOException"); >>> - } catch (IOException e) { >>> - // Expected >>> - } >>> - >>> - // Test for method >> java.io.BufferedInputStream(java.io.InputStream, int) >>> - >>> - // Create buffer with exact size of file >>> - is = new BufferedInputStream(isFile, this.fileString.length()); >>> - // Ensure buffer gets filled by evaluating one read >>> - is.read(); >>> - // Close underlying FileInputStream, all but 1 buffered bytes >> should >>> - // still be available. >>> - isFile.close(); >>> - // Read the remaining buffered characters, no IOException should >>> - // occur. >>> - is.skip(this.fileString.length() - 2); >>> - is.read(); >>> - try { >>> - // is.read should now throw an exception because it will >> have to >>> - // be filled. >>> - is.read(); >>> - fail("Exception should have been triggered by read()"); >>> - } catch (IOException e) { >>> - // Expected >>> - } >>> - >>> - // regression test for harmony-2407 >>> - new MockBufferedInputStream(null); >>> - assertNotNull(MockBufferedInputStream.buf); >>> - MockBufferedInputStream.buf = null; >>> - new MockBufferedInputStream(null, 100); >>> - assertNotNull(MockBufferedInputStream.buf); >>> - } >>> - >>> - static class MockBufferedInputStream extends BufferedInputStream { >>> - static byte[] buf; >>> - >>> - MockBufferedInputStream(InputStream is) throws IOException { >>> - super(is); >>> - buf = super.buf; >>> - } >>> - >>> - MockBufferedInputStream(InputStream is, int size) throws >> IOException { >>> - super(is, size); >>> - buf = super.buf; >>> - } >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#available() >>> - */ >>> - public void test_available() throws IOException { >>> - assertTrue("Returned incorrect number of available bytes", is >>> - .available() == fileString.length()); >>> - >>> - // Test that a closed stream throws an IOE for available() >>> - BufferedInputStream bis = new BufferedInputStream( >>> - new ByteArrayInputStream(new byte[] { 'h', 'e', 'l', >> 'l', 'o', >>> - ' ', 't', 'i', 'm' })); >>> - int available = bis.available(); >>> - bis.close(); >>> - assertTrue(available != 0); >>> - >>> - try { >>> - bis.available(); >>> - fail("Expected test to throw IOE."); >>> - } catch (IOException ex) { >>> - // expected >>> - } >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#close() >>> - */ >>> - public void test_close() throws IOException { >>> - new BufferedInputStream(isFile).close(); >>> - >>> - // regression for HARMONY-667 >>> - BufferedInputStream buf = new BufferedInputStream(null, 5); >>> - buf.close(); >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#mark(int) >>> - */ >>> - public void test_markI() throws IOException { >>> - byte[] buf1 = new byte[100]; >>> - byte[] buf2 = new byte[100]; >>> - is.skip(3000); >>> - is.mark(1000); >>> - is.read(buf1, 0, buf1.length); >>> - is.reset(); >>> - is.read(buf2, 0, buf2.length); >>> - is.reset(); >>> - assertTrue("Failed to mark correct position", new String(buf1, >> 0, >>> - buf1.length).equals(new String(buf2, 0, buf2.length))); >>> - >>> - byte[] bytes = new byte[256]; >>> - for (int i = 0; i < 256; i++) { >>> - bytes[i] = (byte) i; >>> - } >>> - InputStream in = new BufferedInputStream( >>> - new ByteArrayInputStream(bytes), 12); >>> - in.skip(6); >>> - in.mark(14); >>> - in.read(new byte[14], 0, 14); >>> - in.reset(); >>> - assertTrue("Wrong bytes", in.read() == 6 && in.read() == 7); >>> - >>> - in = new BufferedInputStream(new ByteArrayInputStream(bytes), >> 12); >>> - in.skip(6); >>> - in.mark(8); >>> - in.skip(7); >>> - in.reset(); >>> - assertTrue("Wrong bytes 2", in.read() == 6 && in.read() == 7); >>> - >>> - BufferedInputStream buf = new BufferedInputStream( >>> - new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), >> 2); >>> - buf.mark(3); >>> - bytes = new byte[3]; >>> - int result = buf.read(bytes); >>> - assertEquals(3, result); >>> - assertEquals("Assert 0:", 0, bytes[0]); >>> - assertEquals("Assert 1:", 1, bytes[1]); >>> - assertEquals("Assert 2:", 2, bytes[2]); >>> - assertEquals("Assert 3:", 3, buf.read()); >>> - >>> - buf = new BufferedInputStream(new ByteArrayInputStream(new >> byte[] { 0, >>> - 1, 2, 3, 4 }), 2); >>> - buf.mark(3); >>> - bytes = new byte[4]; >>> - result = buf.read(bytes); >>> - assertEquals(4, result); >>> - assertEquals("Assert 4:", 0, bytes[0]); >>> - assertEquals("Assert 5:", 1, bytes[1]); >>> - assertEquals("Assert 6:", 2, bytes[2]); >>> - assertEquals("Assert 7:", 3, bytes[3]); >>> - assertEquals("Assert 8:", 4, buf.read()); >>> - assertEquals("Assert 9:", -1, buf.read()); >>> - >>> - buf = new BufferedInputStream(new ByteArrayInputStream(new >> byte[] { 0, >>> - 1, 2, 3, 4 }), 2); >>> - buf.mark(Integer.MAX_VALUE); >>> - buf.read(); >>> - buf.close(); >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#markSupported() >>> - */ >>> - public void test_markSupported() { >>> - assertTrue("markSupported returned incorrect value", >> is.markSupported()); >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#read() >>> - */ >>> - public void test_read() throws IOException { >>> - int c = is.read(); >>> - assertTrue("read returned incorrect char", c == >> fileString.charAt(0)); >>> - >>> - byte[] bytes = new byte[256]; >>> - for (int i = 0; i < 256; i++) { >>> - bytes[i] = (byte) i; >>> - } >>> - InputStream in = new BufferedInputStream( >>> - new ByteArrayInputStream(bytes), 12); >>> - assertEquals("Wrong initial byte", 0, in.read()); // Fill the >>> - // buffer >>> - byte[] buf = new byte[14]; >>> - in.read(buf, 0, 14); // Read greater than the buffer >>> - assertTrue("Wrong block read data", new String(buf, 0, 14) >>> - .equals(new String(bytes, 1, 14))); >>> - assertEquals("Wrong bytes", 15, in.read()); // Check next byte >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#read(byte[], int, int) >>> - */ >>> - public void test_read$BII_Exception() throws IOException { >>> - BufferedInputStream bis = new BufferedInputStream(null); >>> - try { >>> - bis.read(null, -1, -1); >>> - fail("should throw NullPointerException"); >>> - } catch (NullPointerException e) { >>> - // expected >>> - } >>> - >>> - try { >>> - bis.read(new byte[0], -1, -1); >>> - fail("should throw IndexOutOfBoundsException"); >>> - } catch (IndexOutOfBoundsException e) { >>> - // expected >>> - } >>> - >>> - try { >>> - bis.read(new byte[0], 1, -1); >>> - fail("should throw IndexOutOfBoundsException"); >>> - } catch (IndexOutOfBoundsException e) { >>> - // expected >>> - } >>> - >>> - try { >>> - bis.read(new byte[0], 1, 1); >>> - fail("should throw IndexOutOfBoundsException"); >>> - } catch (IndexOutOfBoundsException e) { >>> - // expected >>> - } >>> - >>> - bis.close(); >>> - >>> - try { >>> - bis.read(null, -1, -1); >>> - fail("should throw IOException"); >>> - } catch (IOException e) { >>> - // expected >>> - } >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#read(byte[], int, int) >>> - */ >>> - public void test_read$BII() throws IOException { >>> - byte[] buf1 = new byte[100]; >>> - is.skip(3000); >>> - is.mark(1000); >>> - is.read(buf1, 0, buf1.length); >>> - assertTrue("Failed to read correct data", new String(buf1, 0, >>> - buf1.length).equals(fileString.substring(3000, 3100))); >>> - >>> - BufferedInputStream bufin = new BufferedInputStream(new >> InputStream() { >>> - int size = 2, pos = 0; >>> - >>> - byte[] contents = new byte[size]; >>> - >>> - @Override >>> - public int read() throws IOException { >>> - if (pos >= size) { >>> - throw new IOException("Read past end of data"); >>> - } >>> - return contents[pos++]; >>> - } >>> - >>> - @Override >>> - public int read(byte[] buf, int off, int len) throws >> IOException { >>> - if (pos >= size) { >>> - throw new IOException("Read past end of data"); >>> - } >>> - int toRead = len; >>> - if (toRead > available()) { >>> - toRead = available(); >>> - } >>> - System.arraycopy(contents, pos, buf, off, toRead); >>> - pos += toRead; >>> - return toRead; >>> - } >>> - >>> - @Override >>> - public int available() { >>> - return size - pos; >>> - } >>> - }); >>> - bufin.read(); >>> - int result = bufin.read(new byte[2], 0, 2); >>> - assertTrue("Incorrect result: " + result, result == 1); >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#reset() >>> - */ >>> - public void test_reset() throws IOException { >>> - byte[] buf1 = new byte[10]; >>> - byte[] buf2 = new byte[10]; >>> - is.mark(2000); >>> - is.read(buf1, 0, 10); >>> - is.reset(); >>> - is.read(buf2, 0, 10); >>> - is.reset(); >>> - assertTrue("Reset failed", new String(buf1, 0, buf1.length) >>> - .equals(new String(buf2, 0, buf2.length))); >>> - >>> - BufferedInputStream bIn = new BufferedInputStream( >>> - new ByteArrayInputStream("1234567890".getBytes())); >>> - bIn.mark(10); >>> - for (int i = 0; i < 11; i++) { >>> - bIn.read(); >>> - } >>> - bIn.reset(); >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#reset() >>> - */ >>> - public void test_reset_Exception() throws IOException { >>> - BufferedInputStream bis = new BufferedInputStream(null); >>> - >>> - // throws IOException with message "Mark has been invalidated" >>> - try { >>> - bis.reset(); >>> - fail("should throw IOException"); >>> - } catch (IOException e) { >>> - // expected >>> - } >>> - >>> - // does not throw IOException >>> - bis.mark(1); >>> - bis.reset(); >>> - >>> - bis.close(); >>> - >>> - // throws IOException with message "stream is closed" >>> - try { >>> - bis.reset(); >>> - fail("should throw IOException"); >>> - } catch (IOException e) { >>> - // expected >>> - } >>> - } >>> - >>> - /** >>> - * @tests java.io.BufferedInputStream#skip(long) >>> - */ >>> - public void test_skipJ() throws IOException { >>> - byte[] buf1 = new byte[10]; >>> - is.mark(2000); >>> - is.skip(1000); >>> - is.read(buf1, 0, buf1.length); >>> - is.reset(); >>> - assertTrue("Failed to skip to correct position", new >> String(buf1, 0, >>> - buf1.length).equals(fileString.substring(1000, 1010))); >>> - >>> - // regression for HARMONY-667 >>> - try { >>> - BufferedInputStream buf = new BufferedInputStream(null, 5); >>> - buf.skip(10); >>> - fail("Should throw IOException"); >>> - } catch (IOException e) { >>> - // Expected >>> - } >>> - } >>> - >>> - /** >>> - * Sets up the fixture, for example, open a network connection. This >> method >>> - * is called before a test is executed. >>> - */ >>> - @Override >>> - protected void setUp() throws IOException { >>> - fileName = System.getProperty("user.dir"); >>> - String separator = System.getProperty("file.separator"); >>> - if (fileName.charAt(fileName.length() - 1) == >> separator.charAt(0)) { >>> - fileName = Support_PlatformFile.getNewPlatformFile(fileName, >>> - "input.tst"); >>> - } else { >>> - fileName = Support_PlatformFile.getNewPlatformFile(fileName >>> - + separator, "input.tst"); >>> - } >>> - OutputStream fos = new FileOutputStream(fileName); >>> - fos.write(fileString.getBytes()); >>> - fos.close(); >>> - isFile = new FileInputStream(fileName); >>> - is = new BufferedInputStream(isFile); >>> - } >>> - >>> - /** >>> - * Tears down the fixture, for example, close a network connection. >> This >>> - * method is called after a test is executed. >>> - */ >>> - @Override >>> - protected void tearDown() { >>> - try { >>> - is.close(); >>> - } catch (Exception e) { >>> - } >>> - try { >>> - File f = new File(fileName); >>> - f.delete(); >>> - } catch (Exception e) { >>> - } >>> - } >>> -} >>> +/* >>> + * 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.harmony.luni.tests.java.io; >>> + >>> +import java.io.BufferedInputStream; >>> +import java.io.ByteArrayInputStream; >>> +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 junit.framework.TestCase; >>> +import tests.support.Support_PlatformFile; >>> + >>> +public class BufferedInputStreamTest extends TestCase { >>> + >>> + public String fileName; >>> + >>> + private BufferedInputStream is; >>> + >>> + private FileInputStream isFile; >>> + >>> + byte[] ibuf = new byte[4096]; >>> + >>> + public String fileString = >> "Test_All_Tests\nTest_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\nTest_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\nTest_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\nTest_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\nTest_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\nTest_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\nTest_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang >> _Cl >> >> assNotFoundException\nTest_java_lang_CloneNotSupportedException\nTest_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\nTest_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\nTest_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\nTest_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\nTest_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\nTest_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\nTest_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\nTest_java_l a >> ng_ >> >> Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\nTest_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\nTest_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\nTest_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\nTest_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\nTest_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\nTest_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\nTest_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_ S >> ock >> >> etException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\nTest_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\nTest_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\nTest_java_util_tm\nTest_java_util_Vector\n"; >>> + >>> + /* >>> + * @tests java.io.BufferedInputStream(InputStream) >>> + */ >>> + public void test_ConstructorLjava_io_InputStream() { >>> + try { >>> + BufferedInputStream str = new BufferedInputStream(null); >>> + str.read(); >>> + fail("Expected an IOException"); >>> + } catch (IOException e) { >>> + // Expected >>> + } >>> + } >>> + >>> + /* >>> + * @tests java.io.BufferedInputStream(InputStream) >>> + */ >>> + public void test_ConstructorLjava_io_InputStreamI() throws >> IOException { >>> + try { >>> + BufferedInputStream str = new BufferedInputStream(null, 1); >>> + str.read(); >>> + fail("Expected an IOException"); >>> + } catch (IOException e) { >>> + // Expected >>> + } >>> + >>> + // Test for method >> java.io.BufferedInputStream(java.io.InputStream, int) >>> + >>> + // Create buffer with exact size of file >>> + is = new BufferedInputStream(isFile, this.fileString.length()); >>> + // Ensure buffer gets filled by evaluating one read >>> + is.read(); >>> + // Close underlying FileInputStream, all but 1 buffered bytes >> should >>> + // still be available. >>> + isFile.close(); >>> + // Read the remaining buffered characters, no IOException should >>> + // occur. >>> + is.skip(this.fileString.length() - 2); >>> + is.read(); >>> + try { >>> + // is.read should now throw an exception because it will >> have to >>> + // be filled. >>> + is.read(); >>> + fail("Exception should have been triggered by read()"); >>> + } catch (IOException e) { >>> + // Expected >>> + } >>> + >>> + // regression test for harmony-2407 >>> + new MockBufferedInputStream(null); >>> + assertNotNull(MockBufferedInputStream.buf); >>> + MockBufferedInputStream.buf = null; >>> + new MockBufferedInputStream(null, 100); >>> + assertNotNull(MockBufferedInputStream.buf); >>> + } >>> + >>> + static class MockBufferedInputStream extends BufferedInputStream { >>> + static byte[] buf; >>> + >>> + MockBufferedInputStream(InputStream is) throws IOException { >>> + super(is); >>> + buf = super.buf; >>> + } >>> + >>> + MockBufferedInputStream(InputStream is, int size) throws >> IOException { >>> + super(is, size); >>> + buf = super.buf; >>> + } >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#available() >>> + */ >>> + public void test_available() throws IOException { >>> + assertTrue("Returned incorrect number of available bytes", is >>> + .available() == fileString.length()); >>> + >>> + // Test that a closed stream throws an IOE for available() >>> + BufferedInputStream bis = new BufferedInputStream( >>> + new ByteArrayInputStream(new byte[] { 'h', 'e', 'l', >> 'l', 'o', >>> + ' ', 't', 'i', 'm' })); >>> + int available = bis.available(); >>> + bis.close(); >>> + assertTrue(available != 0); >>> + >>> + try { >>> + bis.available(); >>> + fail("Expected test to throw IOE."); >>> + } catch (IOException ex) { >>> + // expected >>> + } >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#close() >>> + */ >>> + public void test_close() throws IOException { >>> + new BufferedInputStream(isFile).close(); >>> + >>> + // regression for HARMONY-667 >>> + BufferedInputStream buf = new BufferedInputStream(null, 5); >>> + buf.close(); >>> + >>> + InputStream in = new InputStream() { >>> + Object lock = new Object(); >>> + >>> + @Override >>> + public int read() { >>> + return 1; >>> + } >>> + >>> + @Override >>> + public int read(byte[] buf, int offset, int length) { >>> + synchronized (lock) { >>> + try { >>> + lock.wait(3000); >>> + } catch (InterruptedException e) { >>> + // Ignore >>> + } >>> + } >>> + return 1; >>> + } >>> + >>> + @Override >>> + public void close() { >>> + synchronized (lock) { >>> + lock.notifyAll(); >>> + } >>> + } >>> + }; >>> + final BufferedInputStream bufin = new BufferedInputStream(in); >>> + Thread thread = new Thread(new Runnable() { >>> + public void run() { >>> + try { >>> + Thread.sleep(1000); >>> + bufin.close(); >>> + } catch (Exception e) { >>> + // Ignored >>> + } >>> + } >>> + }); >>> + thread.start(); >>> + try { >>> + bufin.read(new byte[100], 0, 99); >>> + fail("Should throw IOException"); >>> + } catch (IOException e) { >>> + // Expected >>> + } >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#mark(int) >>> + */ >>> + public void test_markI() throws IOException { >>> + byte[] buf1 = new byte[100]; >>> + byte[] buf2 = new byte[100]; >>> + is.skip(3000); >>> + is.mark(1000); >>> + is.read(buf1, 0, buf1.length); >>> + is.reset(); >>> + is.read(buf2, 0, buf2.length); >>> + is.reset(); >>> + assertTrue("Failed to mark correct position", new String(buf1, >> 0, >>> + buf1.length).equals(new String(buf2, 0, buf2.length))); >>> + >>> + byte[] bytes = new byte[256]; >>> + for (int i = 0; i < 256; i++) { >>> + bytes[i] = (byte) i; >>> + } >>> + InputStream in = new BufferedInputStream( >>> + new ByteArrayInputStream(bytes), 12); >>> + in.skip(6); >>> + in.mark(14); >>> + in.read(new byte[14], 0, 14); >>> + in.reset(); >>> + assertTrue("Wrong bytes", in.read() == 6 && in.read() == 7); >>> + >>> + in = new BufferedInputStream(new ByteArrayInputStream(bytes), >> 12); >>> + in.skip(6); >>> + in.mark(8); >>> + in.skip(7); >>> + in.reset(); >>> + assertTrue("Wrong bytes 2", in.read() == 6 && in.read() == 7); >>> + >>> + BufferedInputStream buf = new BufferedInputStream( >>> + new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), >> 2); >>> + buf.mark(3); >>> + bytes = new byte[3]; >>> + int result = buf.read(bytes); >>> + assertEquals(3, result); >>> + assertEquals("Assert 0:", 0, bytes[0]); >>> + assertEquals("Assert 1:", 1, bytes[1]); >>> + assertEquals("Assert 2:", 2, bytes[2]); >>> + assertEquals("Assert 3:", 3, buf.read()); >>> + >>> + buf = new BufferedInputStream(new ByteArrayInputStream(new >> byte[] { 0, >>> + 1, 2, 3, 4 }), 2); >>> + buf.mark(3); >>> + bytes = new byte[4]; >>> + result = buf.read(bytes); >>> + assertEquals(4, result); >>> + assertEquals("Assert 4:", 0, bytes[0]); >>> + assertEquals("Assert 5:", 1, bytes[1]); >>> + assertEquals("Assert 6:", 2, bytes[2]); >>> + assertEquals("Assert 7:", 3, bytes[3]); >>> + assertEquals("Assert 8:", 4, buf.read()); >>> + assertEquals("Assert 9:", -1, buf.read()); >>> + >>> + buf = new BufferedInputStream(new ByteArrayInputStream(new >> byte[] { 0, >>> + 1, 2, 3, 4 }), 2); >>> + buf.mark(Integer.MAX_VALUE); >>> + buf.read(); >>> + buf.close(); >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#markSupported() >>> + */ >>> + public void test_markSupported() { >>> + assertTrue("markSupported returned incorrect value", >> is.markSupported()); >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#read() >>> + */ >>> + public void test_read() throws IOException { >>> + int c = is.read(); >>> + assertTrue("read returned incorrect char", c == >> fileString.charAt(0)); >>> + >>> + byte[] bytes = new byte[256]; >>> + for (int i = 0; i < 256; i++) { >>> + bytes[i] = (byte) i; >>> + } >>> + InputStream in = new BufferedInputStream( >>> + new ByteArrayInputStream(bytes), 12); >>> + assertEquals("Wrong initial byte", 0, in.read()); // Fill the >>> + // buffer >>> + byte[] buf = new byte[14]; >>> + in.read(buf, 0, 14); // Read greater than the buffer >>> + assertTrue("Wrong block read data", new String(buf, 0, 14) >>> + .equals(new String(bytes, 1, 14))); >>> + assertEquals("Wrong bytes", 15, in.read()); // Check next byte >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#read(byte[], int, int) >>> + */ >>> + public void test_read$BII_Exception() throws IOException { >>> + BufferedInputStream bis = new BufferedInputStream(null); >>> + try { >>> + bis.read(null, -1, -1); >>> + fail("should throw NullPointerException"); >>> + } catch (NullPointerException e) { >>> + // expected >>> + } >>> + >>> + try { >>> + bis.read(new byte[0], -1, -1); >>> + fail("should throw IndexOutOfBoundsException"); >>> + } catch (IndexOutOfBoundsException e) { >>> + // expected >>> + } >>> + >>> + try { >>> + bis.read(new byte[0], 1, -1); >>> + fail("should throw IndexOutOfBoundsException"); >>> + } catch (IndexOutOfBoundsException e) { >>> + // expected >>> + } >>> + >>> + try { >>> + bis.read(new byte[0], 1, 1); >>> + fail("should throw IndexOutOfBoundsException"); >>> + } catch (IndexOutOfBoundsException e) { >>> + // expected >>> + } >>> + >>> + bis.close(); >>> + >>> + try { >>> + bis.read(null, -1, -1); >>> + fail("should throw IOException"); >>> + } catch (IOException e) { >>> + // expected >>> + } >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#read(byte[], int, int) >>> + */ >>> + public void test_read$BII() throws IOException { >>> + byte[] buf1 = new byte[100]; >>> + is.skip(3000); >>> + is.mark(1000); >>> + is.read(buf1, 0, buf1.length); >>> + assertTrue("Failed to read correct data", new String(buf1, 0, >>> + buf1.length).equals(fileString.substring(3000, 3100))); >>> + >>> + BufferedInputStream bufin = new BufferedInputStream(new >> InputStream() { >>> + int size = 2, pos = 0; >>> + >>> + byte[] contents = new byte[size]; >>> + >>> + @Override >>> + public int read() throws IOException { >>> + if (pos >= size) { >>> + throw new IOException("Read past end of data"); >>> + } >>> + return contents[pos++]; >>> + } >>> + >>> + @Override >>> + public int read(byte[] buf, int off, int len) throws >> IOException { >>> + if (pos >= size) { >>> + throw new IOException("Read past end of data"); >>> + } >>> + int toRead = len; >>> + if (toRead > available()) { >>> + toRead = available(); >>> + } >>> + System.arraycopy(contents, pos, buf, off, toRead); >>> + pos += toRead; >>> + return toRead; >>> + } >>> + >>> + @Override >>> + public int available() { >>> + return size - pos; >>> + } >>> + }); >>> + bufin.read(); >>> + int result = bufin.read(new byte[2], 0, 2); >>> + assertTrue("Incorrect result: " + result, result == 1); >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#reset() >>> + */ >>> + public void test_reset() throws IOException { >>> + byte[] buf1 = new byte[10]; >>> + byte[] buf2 = new byte[10]; >>> + is.mark(2000); >>> + is.read(buf1, 0, 10); >>> + is.reset(); >>> + is.read(buf2, 0, 10); >>> + is.reset(); >>> + assertTrue("Reset failed", new String(buf1, 0, buf1.length) >>> + .equals(new String(buf2, 0, buf2.length))); >>> + >>> + BufferedInputStream bIn = new BufferedInputStream( >>> + new ByteArrayInputStream("1234567890".getBytes())); >>> + bIn.mark(10); >>> + for (int i = 0; i < 11; i++) { >>> + bIn.read(); >>> + } >>> + bIn.reset(); >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#reset() >>> + */ >>> + public void test_reset_Exception() throws IOException { >>> + BufferedInputStream bis = new BufferedInputStream(null); >>> + >>> + // throws IOException with message "Mark has been invalidated" >>> + try { >>> + bis.reset(); >>> + fail("should throw IOException"); >>> + } catch (IOException e) { >>> + // expected >>> + } >>> + >>> + // does not throw IOException >>> + bis.mark(1); >>> + bis.reset(); >>> + >>> + bis.close(); >>> + >>> + // throws IOException with message "stream is closed" >>> + try { >>> + bis.reset(); >>> + fail("should throw IOException"); >>> + } catch (IOException e) { >>> + // expected >>> + } >>> + } >>> + >>> + /** >>> + * @tests java.io.BufferedInputStream#skip(long) >>> + */ >>> + public void test_skipJ() throws IOException { >>> + byte[] buf1 = new byte[10]; >>> + is.mark(2000); >>> + is.skip(1000); >>> + is.read(buf1, 0, buf1.length); >>> + is.reset(); >>> + assertTrue("Failed to skip to correct position", new >> String(buf1, 0, >>> + buf1.length).equals(fileString.substring(1000, 1010))); >>> + >>> + // regression for HARMONY-667 >>> + try { >>> + BufferedInputStream buf = new BufferedInputStream(null, 5); >>> + buf.skip(10); >>> + fail("Should throw IOException"); >>> + } catch (IOException e) { >>> + // Expected >>> + } >>> + } >>> + >>> + /** >>> + * Sets up the fixture, for example, open a network connection. This >> method >>> + * is called before a test is executed. >>> + */ >>> + @Override >>> + protected void setUp() throws IOException { >>> + fileName = System.getProperty("user.dir"); >>> + String separator = System.getProperty("file.separator"); >>> + if (fileName.charAt(fileName.length() - 1) == >> separator.charAt(0)) { >>> + fileName = Support_PlatformFile.getNewPlatformFile(fileName, >>> + "input.tst"); >>> + } else { >>> + fileName = Support_PlatformFile.getNewPlatformFile(fileName >>> + + separator, "input.tst"); >>> + } >>> + OutputStream fos = new FileOutputStream(fileName); >>> + fos.write(fileString.getBytes()); >>> + fos.close(); >>> + isFile = new FileInputStream(fileName); >>> + is = new BufferedInputStream(isFile); >>> + } >>> + >>> + /** >>> + * Tears down the fixture, for example, close a network connection. >> This >>> + * method is called after a test is executed. >>> + */ >>> + @Override >>> + protected void tearDown() { >>> + try { >>> + is.close(); >>> + } catch (Exception e) { >>> + } >>> + try { >>> + File f = new File(fileName); >>> + f.delete(); >>> + } catch (Exception e) { >>> + } >>> + } >>> +} >>> >>> >>> > > >
