Add Java 6's new PipedReader/PipedInputStream constructors.

Also bring back the latest harmony java6 branch tests, and modify them to pass
with our deliberate [spec-compliant] exception changes.

Bug: 2497395
Change-Id: Ifb3f9bf48f8eec4120f9e59b03beb3969cfe0cd3
diff --git a/libcore/luni/src/main/java/java/io/PipedInputStream.java b/libcore/luni/src/main/java/java/io/PipedInputStream.java
index 6d1c007..507371b 100644
--- a/libcore/luni/src/main/java/java/io/PipedInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PipedInputStream.java
@@ -59,7 +59,7 @@
      * {@code in == out}. Writing when the buffer is full will block until free
      * space is available.
      */
-    protected byte buffer[];
+    protected byte[] buffer;
 
     /**
      * The index in {@code buffer} where the next byte will be written.
@@ -103,6 +103,40 @@
     }
 
     /**
+     * Constructs a new unconnected {@code PipedInputStream} with the given
+     * buffer size. The resulting stream must be connected to a
+     * {@code PipedOutputStream} before data may be read from it.
+     * 
+     * @param pipeSize the size of the buffer in bytes.
+     * @throws IllegalArgumentException if pipeSize is less than or equal to zero.
+     * @since 1.6
+     * @hide
+     */
+    public PipedInputStream(int pipeSize) {
+        if (pipeSize <= 0) {
+            throw new IllegalArgumentException("pipe size " + pipeSize + " too small");
+        }
+        buffer = new byte[pipeSize];
+    }
+
+    /**
+     * Constructs a new {@code PipedInputStream} connected to the given {@code PipedOutputStream},
+     * with the given buffer size. Any data written to the output stream can be read from this
+     * input stream.
+     * 
+     * @param out the {@code PipedOutputStream} to connect to.
+     * @param pipeSize the size of the buffer in bytes.
+     * @throws IOException if an I/O error occurs.
+     * @throws IllegalArgumentException if pipeSize is less than or equal to zero.
+     * @since 1.6
+     * @hide
+     */
+    public PipedInputStream(PipedOutputStream out, int pipeSize) throws IOException {
+        this(pipeSize);
+        connect(out);
+    }
+
+    /**
      * Returns the number of bytes that are available before this stream will
      * block. This implementation returns the number of bytes written to this
      * pipe that have not been read yet.
@@ -156,7 +190,9 @@
         if (isConnected) {
             throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
         }
-        buffer = new byte[PipedInputStream.PIPE_SIZE];
+        if (buffer == null) { // We may already have allocated the buffer.
+            buffer = new byte[PipedInputStream.PIPE_SIZE];
+        }
         isConnected = true;
     }
 
diff --git a/libcore/luni/src/main/java/java/io/PipedReader.java b/libcore/luni/src/main/java/java/io/PipedReader.java
index d137a0d..29319fa 100644
--- a/libcore/luni/src/main/java/java/io/PipedReader.java
+++ b/libcore/luni/src/main/java/java/io/PipedReader.java
@@ -103,6 +103,40 @@
     }
 
     /**
+     * Constructs a new unconnected {@code PipedReader} with the given buffer size.
+     * The resulting reader must be connected to a {@code PipedWriter} before
+     * data may be read from it.
+     * 
+     * @param pipeSize the size of the buffer in chars.
+     * @throws IllegalArgumentException if pipeSize is less than or equal to zero.
+     * @since 1.6
+     * @hide
+     */
+    public PipedReader(int pipeSize) {
+        if (pipeSize <= 0) {
+            throw new IllegalArgumentException("pipe size " + pipeSize + " too small");
+        }
+        buffer = new char[pipeSize];
+    }
+
+    /**
+     * Constructs a new {@code PipedReader} connected to the given {@code PipedWriter},
+     * with the given buffer size. Any data written to the writer can be read from
+     * this reader.
+     * 
+     * @param out the {@code PipedWriter} to connect to.
+     * @param pipeSize the size of the buffer in chars.
+     * @throws IOException if an I/O error occurs
+     * @throws IllegalArgumentException if pipeSize is less than or equal to zero.
+     * @since 1.6
+     * @hide
+     */
+    public PipedReader(PipedWriter out, int pipeSize) throws IOException {
+        this(pipeSize);
+        connect(out);
+    }
+
+    /**
      * Closes this reader. This implementation releases the buffer used for
      * the pipe and notifies all threads waiting to read or write.
      *
@@ -112,6 +146,7 @@
     @Override
     public synchronized void close() throws IOException {
         buffer = null;
+        isClosed = true;
         notifyAll();
     }
 
@@ -139,7 +174,9 @@
         if (isConnected) {
             throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
         }
-        buffer = new char[PIPE_SIZE];
+        if (buffer == null) { // We may already have allocated the buffer.
+            buffer = new char[PIPE_SIZE];
+        }
         isConnected = true;
     }
 
diff --git a/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java b/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
index 671bfe9..b423659 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
@@ -20,121 +20,92 @@
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
-@TestTargetClass(PipedInputStream.class) 
 public class PipedInputStreamTest extends junit.framework.TestCase {
 
-    static class PWriter implements Runnable {
-        PipedOutputStream pos;
+	static class PWriter implements Runnable {
+		PipedOutputStream pos;
 
-        public byte bytes[];
+		public byte bytes[];
 
-        public void run() {
-            try {
-                pos.write(bytes);   
-                synchronized (this) {
-                    notify();
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                System.out.println("Error while running the writer thread.");
-            }
-        }
+		public void run() {
+			try {
+				pos.write(bytes);
+				synchronized (this) {
+					notify();
+				}
+			} catch (IOException e) {
+				e.printStackTrace(System.out);
+				System.out.println("Could not write bytes");
+			}
+		}
 
-        public PWriter(PipedOutputStream pout, int nbytes) {
-            pos = pout;
-            bytes = new byte[nbytes];
-            for (int i = 0; i < bytes.length; i++)
-                bytes[i] = (byte) (System.currentTimeMillis() % 9);
-        }
-    }
+		public PWriter(PipedOutputStream pout, int nbytes) {
+			pos = pout;
+			bytes = new byte[nbytes];
+			for (int i = 0; i < bytes.length; i++) {
+				bytes[i] = (byte) (System.currentTimeMillis() % 9);
+		    }
+		}
+	}
 
-    static class PWriter2 implements Runnable {
-        PipedOutputStream pos;
+	Thread t;
 
-        public boolean keepRunning = true;
+	PWriter pw;
 
-        public void run() {
-            try {
-                pos.write(42);
-                pos.close();
-                while (keepRunning) {
-                    Thread.sleep(1000);
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                System.out.println("Error while running the writer thread.");
-            }
-        }
+	PipedInputStream pis;
 
-        public PWriter2(PipedOutputStream pout) {
-            pos = pout;
-        }
-    }
+	PipedOutputStream pos;
 
-    Thread t;
+	/**
+	 * @tests java.io.PipedInputStream#PipedInputStream()
+	 */
+	public void test_Constructor() {
+		// Test for method java.io.PipedInputStream()
+		// Used in tests
+	}
 
-    PWriter pw;
-
-    PipedInputStream pis;
-
-    PipedOutputStream pos;
-
-    /**
-     * @tests java.io.PipedInputStream#PipedInputStream()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "PipedInputStream",
-        args = {}
-    )
-    public void test_Constructor() throws IOException {
-        pis = new PipedInputStream();
-        assertEquals("There should not be any bytes available. ", 0, pis.available());
-        pis.close();
-    }
-
-    /**
-     * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "PipedInputStream",
-        args = {java.io.PipedOutputStream.class}
-    )
-    public void test_ConstructorLjava_io_PipedOutputStream() throws IOException {
-        pos = new PipedOutputStream(new PipedInputStream());
-        
-        try {
-            pis = new PipedInputStream(pos);
-            fail("IOException expected since the output stream is already connected.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
+	/**
+	 * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream)
+	 */
+	public void test_ConstructorLjava_io_PipedOutputStream() throws Exception {
+        // Test for method java.io.PipedInputStream(java.io.PipedOutputStream)
         pis = new PipedInputStream(new PipedOutputStream());
-        assertEquals("There should not be any bytes available. ", 0, pis.available());
-        
-        pis.close();
-        pos.close();
+        pis.available();
+    }
+
+
+    /**
+     * @test java.io.PipedInputStream#read()
+     */
+    public void test_readException() throws IOException {
+        pis = new PipedInputStream();
+        pos = new PipedOutputStream();
+
+        try {
+            pis.connect(pos);
+            t = new Thread(pw = new PWriter(pos, 1000));
+            t.start();
+            assertTrue(t.isAlive());
+            while (true) {
+                pis.read();
+                t.interrupt();
+            }
+        } catch (IOException e) {
+            if (!e.getMessage().contains("Write end dead") && !e.getMessage().contains("Pipe broken")) { // android-changed
+                throw e;
+            }
+        } finally {
+            try {
+                pis.close();
+                pos.close();
+            } catch (IOException ee) {}
+        }
     }
 
     /**
      * @tests java.io.PipedInputStream#available()
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "No IOException checking because it is never thrown in the source code.",
-        method = "available",
-        args = {}
-    )
     public void test_available() throws Exception {
-        // Test for method int java.io.PipedInputStream.available()
         pis = new PipedInputStream();
         pos = new PipedOutputStream();
 
@@ -145,63 +116,49 @@
         synchronized (pw) {
             pw.wait(10000);
         }
-        assertEquals("Test 1: Incorrect number of bytes available. ",
-                     1000, pis.available());
+        assertTrue("Available returned incorrect number of bytes: "
+                + pis.available(), pis.available() == 1000);
 
         PipedInputStream pin = new PipedInputStream();
         PipedOutputStream pout = new PipedOutputStream(pin);
         // We know the PipedInputStream buffer size is 1024.
         // Writing another byte would cause the write to wait
         // for a read before returning
-        for (int i = 0; i < 1024; i++)
+        for (int i = 0; i < 1024; i++) {
             pout.write(i);
-        assertEquals("Test 2: Incorrect number of bytes available. ", 
-                     1024 , pin.available());
+        }
+        assertEquals("Incorrect available count", 1024 , pin.available());
     }
 
-    /**
-     * @tests java.io.PipedInputStream#close()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "No IOException checking because it is never thrown in the source code.",
-        method = "close",
-        args = {}
-    )
-    public void test_close() throws IOException {
-        // Test for method void java.io.PipedInputStream.close()
-        pis = new PipedInputStream();
-        pos = new PipedOutputStream();
+	/**
+	 * @tests java.io.PipedInputStream#close()
+	 */
+	public void test_close() throws IOException {
+		// Test for method void java.io.PipedInputStream.close()
+		pis = new PipedInputStream();
+		pos = new PipedOutputStream();
         pis.connect(pos);
         pis.close();
-        try {
-            pos.write((byte) 127);
-            fail("IOException expected.");
-        } catch (IOException e) {
-            // The spec for PipedInput says an exception should be thrown if
-            // a write is attempted to a closed input. The PipedOuput spec
-            // indicates that an exception should be thrown only when the
-            // piped input thread is terminated without closing
-            return;
-        }
-    }
+		try {
+			pos.write((byte) 127);
+            fail("Failed to throw expected exception");
+		} catch (IOException e) {
+			// The spec for PipedInput saya an exception should be thrown if
+			// a write is attempted to a closed input. The PipedOuput spec
+			// indicates that an exception should be thrown only when the
+			// piped input thread is terminated without closing
+			return;
+		}
+	}
 
-    /**
-     * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "connect",
-        args = {java.io.PipedOutputStream.class}
-    )
-    public void test_connectLjava_io_PipedOutputStream() throws Exception {
-        // Test for method void
-        // java.io.PipedInputStream.connect(java.io.PipedOutputStream)
+	/**
+	 * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream)
+	 */
+	public void test_connectLjava_io_PipedOutputStream() throws Exception {
         pis = new PipedInputStream();
         pos = new PipedOutputStream();
-        assertEquals("Test 1: Not-connected pipe returned more than zero available bytes. ", 
-                     0, pis.available());
+        assertEquals("Non-conected pipe returned non-zero available bytes", 0,
+                pis.available());
 
         pis.connect(pos);
         t = new Thread(pw = new PWriter(pos, 1000));
@@ -210,142 +167,50 @@
         synchronized (pw) {
             pw.wait(10000);
         }
-        assertEquals("Test 2: Unexpected number of bytes available. ", 
-                     1000, pis.available());
-
-        try {
-            pis.connect(pos);
-            fail("Test 3: IOException expected when reconnecting the pipe.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
-        pis.close();
-        pos.close();
+        assertEquals("Available returned incorrect number of bytes", 1000, pis
+                .available());
     }
 
-    /**
-     * @tests java.io.PipedInputStream#read()
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "",
-        method = "read",
-        args = {}
-    )
-    public void test_read() throws Exception {
+	/**
+	 * @tests java.io.PipedInputStream#read()
+	 */
+	public void test_read() throws Exception {
         pis = new PipedInputStream();
         pos = new PipedOutputStream();
 
-        try {
-            pis.read();
-            fail("Test 1: IOException expected since the stream is not connected.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
         pis.connect(pos);
-        t = new Thread(pw = new PWriter(pos, 100));
+        t = new Thread(pw = new PWriter(pos, 1000));
         t.start();
 
         synchronized (pw) {
-            pw.wait(5000);
+            pw.wait(10000);
         }
-        assertEquals("Test 2: Unexpected number of bytes available. ", 
-                     100, pis.available());
-        
-        for (int i = 0; i < 100; i++) {
-            assertEquals("Test 3: read() returned incorrect byte. ", 
-                         pw.bytes[i], (byte) pis.read());
-        }
-
-        try {
-            pis.read();
-            fail("Test 4: IOException expected since the thread that has " +
-                 "written to the pipe is no longer alive.");
-        } catch (IOException e) {
-            // Expected.
-        }
-
-        pis.close();
-        try {
-            pis.read();
-            fail("Test 5: IOException expected since the stream is closed.");
-        } catch (IOException e) {
-            // Expected.
-        }
+        assertEquals("Available returned incorrect number of bytes", 1000, pis
+                .available());
+        assertEquals("read returned incorrect byte", pw.bytes[0], (byte) pis
+                .read());
     }
 
-    /**
-     * @tests java.io.PipedInputStream#read()
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Checks that read returns -1 if the PipedOutputStream connected to this PipedInputStream is closed.",
-        method = "read",
-        args = {}
-    )
-    public void test_read_2() throws Exception {
-        Thread writerThread;
-        PWriter2 pwriter;
-        
-        pos = new PipedOutputStream(); 
-        pis = new PipedInputStream(pos);
-        writerThread = new Thread(pwriter = new PWriter2(pos));
-        writerThread.start();
+	/**
+	 * @tests java.io.PipedInputStream#read(byte[], int, int)
+	 */
+	public void test_read$BII() throws Exception {
+        pis = new PipedInputStream();
+        pos = new PipedOutputStream();
 
-        synchronized (pwriter) {
-            pwriter.wait(5000);
-        }
-        pis.read();
-        assertEquals("Test 1: No more data indication expected. ", -1, pis.read());
-        pwriter.keepRunning = false;
-        
-        pis.close();
-    }
+        pis.connect(pos);
+        t = new Thread(pw = new PWriter(pos, 1000));
+        t.start();
 
-    /**
-     * @tests java.io.PipedInputStream#read(byte[], int, int)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Tests read from unconnected, connected and closed pipe.",
-        method = "read",
-        args = {byte[].class, int.class, int.class}
-    )
-    public void test_read$BII() throws Exception {
         byte[] buf = new byte[400];
-        pis = new PipedInputStream();
-        pos = new PipedOutputStream();
-
-        try {
-            pis.read(buf, 0, 10);
-            fail("Test 1: IOException expected since the stream is not connected.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
-        pis.connect(pos);
-        t = new Thread(pw = new PWriter(pos, 1000));
-        t.start();
-
         synchronized (pw) {
             pw.wait(10000);
         }
-        assertEquals("Test 2: Unexpected number of bytes available. ",
-                     1000, pis.available());
+        assertTrue("Available returned incorrect number of bytes: "
+                + pis.available(), pis.available() == 1000);
         pis.read(buf, 0, 400);
         for (int i = 0; i < 400; i++) {
-            assertEquals("Test 3: read() returned incorrect byte. ", 
-                         pw.bytes[i], buf[i]);
-        }
-        
-        pis.close();
-        try {
-            pis.read(buf, 0, 10);
-            fail("Test 4: IOException expected since the stream is closed.");
-        } catch (IOException e) {
-            // Expected.
+            assertEquals("read returned incorrect byte[]", pw.bytes[i], buf[i]);
         }
     }
 
@@ -353,20 +218,14 @@
      * @tests java.io.PipedInputStream#read(byte[], int, int)
      * Regression for HARMONY-387
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Tests illegal length argument.",
-        method = "read",
-        args = {byte[].class, int.class, int.class}
-    )
     public void test_read$BII_2() throws IOException {
         PipedInputStream obj = new PipedInputStream();
         try {
             obj.read(new byte[0], 0, -1);
-            fail("IndexOutOfBoundsException expected.");
+            fail("IndexOutOfBoundsException expected");
         } catch (IndexOutOfBoundsException t) {
             assertEquals(
-                    "IndexOutOfBoundsException rather than a subclass expected.",
+                    "IndexOutOfBoundsException rather than a subclass expected",
                     IndexOutOfBoundsException.class, t.getClass());
         }
     }
@@ -374,46 +233,34 @@
     /**
      * @tests java.io.PipedInputStream#read(byte[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Tests illegal offset argument.",
-        method = "read",
-        args = {byte[].class, int.class, int.class}
-    )
     public void test_read$BII_3() throws IOException {
         PipedInputStream obj = new PipedInputStream();
         try {
-            obj.read(new byte[10], -1, 1);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected
-            assertTrue(e.getClass().equals(IndexOutOfBoundsException.class));
+            obj.read(new byte[0], -1, 0);
+            fail("IndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException t) {
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException t) {
         }
+    }
+
+    /**
+     * @tests java.io.PipedInputStream#read(byte[], int, int)
+     */
+    public void test_read$BII_4() throws IOException {
+        PipedInputStream obj = new PipedInputStream();
         try {
-            obj.read(new byte[10], 0, -1);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected
-            assertTrue(e.getClass().equals(IndexOutOfBoundsException.class));
-        }
-        try {
-            obj.read(new byte[10], 9, 2);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected
-            assertTrue(e.getClass().equals(IndexOutOfBoundsException.class));
+            obj.read(new byte[0], -1, -1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException t) {
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException t) {
         }
     }
 
     /**
      * @tests java.io.PipedInputStream#receive(int)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "receive",
-        args = {int.class}
-    )
     public void test_receive() throws IOException {
         pis = new PipedInputStream();
         pos = new PipedOutputStream();
@@ -424,13 +271,13 @@
 
             boolean pass = false;
 
-            boolean readerAlive = true;
+            volatile boolean readerAlive = true;
 
             public void run() {
                 try {
                     pos.write(1);
                     while (readerAlive) {
-                        Thread.sleep(100);
+                        ;
                     }
                     try {
                         // should throw exception since reader thread
@@ -440,9 +287,6 @@
                         pass = true;
                     }
                 } catch (IOException e) {
-                    // ignore
-                } catch (InterruptedException e) {
-                    // ignore
                 }
             }
         }
@@ -456,7 +300,8 @@
                 try {
                     pis.read();
                     pass = true;
-                } catch (IOException e) {}
+                } catch (IOException e) {
+                }
             }
         }
         ;
@@ -464,12 +309,14 @@
         Thread readThread = new Thread(readRunnable);
         writeThread.start();
         readThread.start();
-        while (readThread.isAlive())
+        while (readThread.isAlive()) {
             ;
+        }
         writeRunnable.readerAlive = false;
         assertTrue("reader thread failed to read", readRunnable.pass);
-        while (writeThread.isAlive())
+        while (writeThread.isAlive()) {
             ;
+        }
         assertTrue("writer thread failed to recognize dead reader",
                 writeRunnable.pass);
 
@@ -500,7 +347,8 @@
             try {
                 // wait for thread t to get to the call to pis.receive
                 Thread.sleep(100);
-            } catch (InterruptedException e) {}
+            } catch (InterruptedException e) {
+            }
             // now we close
             pos.close();
         }
@@ -515,17 +363,87 @@
                 myRun.pass);
     }
 
-    /**
-     * Tears down the fixture, for example, close a network connection. This
-     * method is called after a test is executed.
-     */
-    protected void tearDown() throws Exception {
-        try {
-            if (t != null) {
-                t.interrupt();
+	/**
+	 * Tears down the fixture, for example, close a network connection. This
+	 * method is called after a test is executed.
+	 */
+	protected void tearDown() throws Exception {
+		try {
+			if (t != null) {
+				t.interrupt();
             }
-        } catch (Exception ignore) {
-        }
+		} catch (Exception ignore) {
+		}
         super.tearDown();
+	}
+	
+	    
+     /**
+     * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream,
+     *        int)
+     * @since 1.6
+     */
+    public void test_Constructor_LPipedOutputStream_I() throws Exception {
+        // Test for method java.io.PipedInputStream(java.io.PipedOutputStream,
+        // int)
+        MockPipedInputStream mpis = new MockPipedInputStream(
+                new PipedOutputStream(), 100);
+        int bufferLength = mpis.bufferLength();
+        assertEquals(100, bufferLength);
+        
+        try {
+            pis = new PipedInputStream(null, -1);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        
+        try {
+            pis = new PipedInputStream(null, 0);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.io.PipedInputStream#PipedInputStream(int)
+     * @since 1.6
+     */
+    public void test_Constructor_I() throws Exception {
+        // Test for method java.io.PipedInputStream(int)
+        MockPipedInputStream mpis = new MockPipedInputStream(100);
+        int bufferLength = mpis.bufferLength();
+        assertEquals(100, bufferLength);
+
+        try {
+            pis = new PipedInputStream(-1);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        
+        try {
+            pis = new PipedInputStream(0);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+	
+    static class MockPipedInputStream extends PipedInputStream {
+
+        public MockPipedInputStream(java.io.PipedOutputStream src,
+                int bufferSize) throws IOException {
+            super(src, bufferSize);
+        }
+
+        public MockPipedInputStream(int bufferSize) {
+            super(bufferSize);
+        }
+
+        public int bufferLength() {
+            return super.buffer.length;
+        }
     }
 }
diff --git a/libcore/luni/src/test/java/tests/api/java/io/PipedReaderTest.java b/libcore/luni/src/test/java/tests/api/java/io/PipedReaderTest.java
index f67790b..edbb5f5 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/PipedReaderTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/PipedReaderTest.java
@@ -17,17 +17,13 @@
 
 package tests.api.java.io;
 
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargetClass; 
-
 import java.io.IOException;
 import java.io.PipedReader;
 import java.io.PipedWriter;
 
-@TestTargetClass(PipedReader.class) 
-public class PipedReaderTest extends junit.framework.TestCase {
+import junit.framework.TestCase;
+
+public class PipedReaderTest extends TestCase {
 
     static class PWriter implements Runnable {
         public PipedWriter pw;
@@ -57,29 +53,6 @@
         }
     }
 
-    static class PWriter2 implements Runnable {
-        PipedWriter pw;
-
-        public boolean keepRunning = true;
-
-        public void run() {
-            try {
-                pw.write('H');
-                pw.close();
-                while (keepRunning) {
-                    Thread.sleep(1000);
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                System.out.println("Error while running the writer thread.");
-            }
-        }
-
-        public PWriter2(PipedWriter writer) {
-            pw = writer;
-        }
-    }
-    
     PipedReader preader;
 
     PWriter pwriter;
@@ -89,88 +62,80 @@
     /**
      * @tests java.io.PipedReader#PipedReader()
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "PipedReader",
-        args = {}
-    )
     public void test_Constructor() {
-        preader = new PipedReader();
-        assertNotNull(preader);
-        try {
-            preader.close();
-        } catch (IOException e) {
-            fail("Unexpeceted IOException");
-        }
+        // Used in test
     }
 
     /**
      * @tests java.io.PipedReader#PipedReader(java.io.PipedWriter)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "PipedReader",
-        args = {java.io.PipedWriter.class}
-    )
     public void test_ConstructorLjava_io_PipedWriter() throws IOException {
-        // Test for method java.io.PipedReader(java.io.PipedWriter)
+        preader = new PipedReader(new PipedWriter());
+    }
+    
+    /**
+     * @tests java.io.PipedReader#PipedReader(java.io.PipedWriter,
+     *        int)
+     * @since 1.6
+     */
+    public void test_Constructor_LPipedWriter_I() throws Exception {
+        // Test for method java.io.PipedReader(java.io.PipedWriter,
+        // int)
         try {
-            preader = new PipedReader(new PipedWriter());
-        } catch (Exception e) {
-            fail("Test 1: Constructor failed: " + e.getMessage());
+            preader = new PipedReader(null, -1);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
         }
-        preader.close();
-            
-        PipedWriter pw = new PipedWriter(new PipedReader());
+        
         try {
-            preader = new PipedReader(pw);
-            fail("Test 2: IOException expected because the writer is already connected.");
-        } catch (IOException e) {
-            // Expected.
+            preader = new PipedReader(null, 0);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.io.PipedReader#PipedReader(int)
+     * @since 1.6
+     */
+    public void test_Constructor_I() throws Exception {
+        // Test for method java.io.PipedReader(int)
+        try {
+            preader = new PipedReader(-1);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        
+        try {
+            preader = new PipedReader(0);
+            fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
         }
     }
 
     /**
      * @tests java.io.PipedReader#close()
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "No IOException checking because it is never thrown in the source code.",
-        method = "close",
-        args = {}
-    )
     public void test_close() throws Exception {
-        // Test for method void java.io.PipedReader.close()
         char[] c = null;
         preader = new PipedReader();
         t = new Thread(new PWriter(preader), "");
         t.start();
         Thread.sleep(500); // Allow writer to start
         c = new char[11];
-        preader.read(c, 0, 5);
+        preader.read(c, 0, 11);
         preader.close();
-        
-        try {
-            preader.read(c, 0, 5);
-            fail("IOException expected because the reader is closed.");
-        } catch (IOException e) {
-            // Expected.
-        }
+        assertEquals("Read incorrect chars", "Hello World", new String(c));
     }
 
     /**
      * @tests java.io.PipedReader#connect(java.io.PipedWriter)
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "connect",
-        args = {java.io.PipedWriter.class}
-    )
     public void test_connectLjava_io_PipedWriter() throws Exception {
-        // Test for method void java.io.PipedReader.connect(java.io.PipedWriter)
         char[] c = null;
 
         preader = new PipedReader();
@@ -181,26 +146,19 @@
         c = new char[11];
         preader.read(c, 0, 11);
 
-        assertEquals("Test 1: Wrong characters read. ", "Hello World", new String(c));
+        assertEquals("Read incorrect chars", "Hello World", new String(c));
         try {
-            preader.connect(new PipedWriter());
-            fail("Test 2: IOException expected because the reader is already connected.");
+            preader.connect(pwriter.pw);
+            fail("Failed to throw exception connecting to pre-connected reader");
         } catch (IOException e) {
-            // Expected.
+            // Expected
         }
     }
 
     /**
      * @tests java.io.PipedReader#read()
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "",
-        method = "read",
-        args = {}
-    )
-    public void test_read_1() throws Exception {
-        // Test for method int java.io.PipedReader.read()
+    public void test_read() throws Exception {
         char[] c = null;
         preader = new PipedReader();
         t = new Thread(new PWriter(preader), "");
@@ -210,62 +168,13 @@
         for (int i = 0; i < c.length; i++) {
             c[i] = (char) preader.read();
         }
-        assertEquals("Test 1: Wrong characters read. ", "Hello World", new String(c));
-        
-        try {
-            preader.read();
-            fail("Test 2: IOException expected since the thread that has " +
-                 "written to the pipe is no longer alive.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
-        preader.close();
-        try {
-            preader.read();
-            fail("Test 3: IOException expected.");
-        } catch (IOException e) {
-            // Expected.
-        }
-    }
-
-    /**
-     * @tests java.io.PipedReader#read()
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Checks that read() returns -1 if the PipedWriter connectedto this PipedReader is closed.",
-        method = "read",
-        args = {}
-    )
-    public void test_read_2() throws Exception {
-        Thread writerThread;
-        PipedWriter pw;
-        PWriter2 pwriter;
-
-        preader = new PipedReader();
-        pw = new PipedWriter(preader);
-        
-        writerThread = new Thread(pwriter = new PWriter2(pw), "PWriter2");
-        writerThread.start();
-        Thread.sleep(500); // Allow writer to start
-        
-        preader.read();
-        assertEquals("Test 1: No more data indication expected. ", -1, preader.read());
-        pwriter.keepRunning = false;
+        assertEquals("Read incorrect chars", "Hello World", new String(c));
     }
 
     /**
      * @tests java.io.PipedReader#read(char[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "IOException checking missed.",
-        method = "read",
-        args = {char[].class, int.class, int.class}
-    )
-    public void test_read$CII_1() throws Exception {
-        // Test for method int java.io.PipedReader.read(char [], int, int)
+    public void test_read$CII() throws Exception {
         char[] c = null;
         preader = new PipedReader();
         t = new Thread(new PWriter(preader), "");
@@ -278,121 +187,231 @@
             n = preader.read(c, x, 11 - x);
             x = x + n;
         }
-        assertEquals("Test 1: Wrong characters read. ", "Hello World", new String(c));
-
-        preader.close();
+        assertEquals("Read incorrect chars", "Hello World", new String(c));
         try {
+            preader.close();
             preader.read(c, 8, 7);
-            fail("Test 2: IOException expected.");
+            fail("Failed to throw exception reading from closed reader");
         } catch (IOException e) {
-            // Expected.
+            // Expected
         }
     }
 
     /**
      * @tests java.io.PipedReader#read(char[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "",
-        method = "read",
-        args = {char[].class, int.class, int.class}
-    )
-    public void test_read$CII_Exception() throws IOException{
+    public void test_read$CII_2() throws IOException {
+        // Regression for HARMONY-387
         PipedWriter pw = new PipedWriter();
-        PipedReader obj = new PipedReader(pw);
+        PipedReader obj = null;
         try {
-            obj.read(new char[10], 0, -1);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected.
-        }
-        try {
-            obj.read(new char[10], -1, 1);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected.
-        }
-        try {
-            obj.read(new char[10], 2, 9);
-            fail("IndexOutOfBoundsException expected.");
-        } catch (IndexOutOfBoundsException e) {
-            // Expected.
-        }
-        try {
-            obj.read(null, 0, 1);
-            fail("NullPointerException expected.");
-        } catch (NullPointerException e) {
-            // Expected.
+            obj = new PipedReader(pw);
+            obj.read(new char[0], (int) 0, (int) -1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException t) {
+            assertEquals(
+                    "IndexOutOfBoundsException rather than a subclass expected",
+                    IndexOutOfBoundsException.class, t.getClass());
         }
     }
 
     /**
-     * @tests java.io.PipedReader#read()
+     * @tests java.io.PipedReader#read(char[], int, int)
      */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Checks that read() returns -1 if the PipedWriter connectedto this PipedReader is closed.",
-        method = "read",
-        args = {}
-    )
-    public void test_read$CII_2() throws Exception {
-        Thread writerThread;
-        PipedWriter pw;
-        PWriter2 pwriter;
-        char[] c = new char[1];
+    public void test_read$CII_3() throws IOException {
+        PipedWriter pw = new PipedWriter();
+        PipedReader obj = null;
+        try {
+            obj = new PipedReader(pw);
+            obj.read(new char[0], (int) -1, (int) 0);
+            fail("IndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException t) {
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException t) {
+            // Expected
+        }
+    }
 
-        preader = new PipedReader();
-        pw = new PipedWriter(preader);
-        
-        writerThread = new Thread(pwriter = new PWriter2(pw), "PWriter2");
-        writerThread.start();
-        Thread.sleep(500); // Allow writer to start
-        
-        preader.read(c, 0, 1);
-        assertEquals("Test 1: No more data indication expected. ", 
-                     -1, preader.read(c, 0, 1));
-        pwriter.keepRunning = false;
+    /**
+     * @tests java.io.PipedReader#read(char[], int, int)
+     */
+    public void test_read$CII_4() throws IOException {
+        PipedWriter pw = new PipedWriter();
+        PipedReader obj = null;
+        try {
+            obj = new PipedReader(pw);
+            obj.read(new char[0], (int) -1, (int) -1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException t) {
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException t) {
+            // Expected
+        }
+    }
+
+    /**
+     * @tests java.io.PipedReader#read(char[], int, int)
+     */
+    public void test_read_$CII_IOException() throws IOException {
+        PipedWriter pw = new PipedWriter();
+        PipedReader pr = new PipedReader(pw);
+        char[] buf = null;
+        pr.close();
+        try {
+            pr.read(buf, 0, 10);
+            fail("Should throws IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pr = new PipedReader();
+        buf = null;
+        pr.close();
+        try {
+            pr.read(buf, 0, 10);
+            fail("Should throws IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        buf = new char[10];
+        pr.close();
+        try {
+            pr.read(buf, -1, 0);
+            fail("Should throws IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        buf = new char[10];
+        pr.close();
+        try {
+            pr.read(buf, 0, -1);
+            fail("Should throws IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        buf = new char[10];
+        pr.close();
+        try {
+            pr.read(buf, 1, 10);
+            fail("Should throws IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        pr.close();
+        try {
+            pr.read(new char[0], -1, -1);
+            fail("should throw IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        pr.close();
+        try {
+            pr.read(null, 0, 1);
+            fail("should throw IOException"); //$NON-NLS-1$
+        } catch (IOException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        try {
+            pr.read(null, -1, 1);
+            fail("should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+        } catch (NullPointerException expected) { // android-added
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        try {
+            pr.read(null, 0, -1);
+            fail("should throw NullPointerException"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        try {
+            pr.read(new char[10], 11, 0);
+            fail("should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
+
+        pw = new PipedWriter();
+        pr = new PipedReader(pw);
+        try {
+            pr.read(null, 1, 0);
+            fail("should throw NullPointerException"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        } finally {
+            pw = null;
+            pr = null;
+        }
     }
 
     /**
      * @tests java.io.PipedReader#ready()
      */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "ready",
-        args = {}
-    )
     public void test_ready() throws Exception {
-        // Test for method boolean java.io.PipedReader.ready()
         char[] c = null;
         preader = new PipedReader();
-        
-        try {
-            preader.ready();
-            fail("Test 1: IOException expected.");
-        } catch (IOException e) {
-            // Expected.
-        }
-        
         t = new Thread(new PWriter(preader), "");
         t.start();
         Thread.sleep(500); // Allow writer to start
-        assertTrue("Test 2: Reader should be ready", preader.ready());
+        assertTrue("Reader should be ready", preader.ready());
         c = new char[11];
         for (int i = 0; i < c.length; i++)
             c[i] = (char) preader.read();
-        assertFalse("Test 3: Reader should not be ready after reading all chars",
+        assertFalse("Reader should not be ready after reading all chars",
                 preader.ready());
-        
-        preader.close();
-        try {
-            preader.ready();
-            fail("Test 4: IOException expected.");
-        } catch (IOException e) {
-            // Expected.
-        }
     }
 
     /**