| /* |
| * 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 tests.api.java.io; |
| |
| import java.io.IOException; |
| 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; |
| |
| 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 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; |
| |
| public boolean keepRunning = true; |
| |
| 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."); |
| } |
| } |
| |
| public PWriter2(PipedOutputStream pout) { |
| pos = pout; |
| } |
| } |
| |
| Thread t; |
| |
| 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. |
| } |
| |
| pis = new PipedInputStream(new PipedOutputStream()); |
| assertEquals("There should not be any bytes available. ", 0, pis.available()); |
| |
| pis.close(); |
| pos.close(); |
| } |
| |
| /** |
| * @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(); |
| |
| pis.connect(pos); |
| t = new Thread(pw = new PWriter(pos, 1000)); |
| t.start(); |
| |
| synchronized (pw) { |
| pw.wait(10000); |
| } |
| assertEquals("Test 1: Incorrect number of bytes available. ", |
| 1000, pis.available()); |
| |
| 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++) |
| pout.write(i); |
| assertEquals("Test 2: Incorrect number of bytes available. ", |
| 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(); |
| 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; |
| } |
| } |
| |
| /** |
| * @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) |
| pis = new PipedInputStream(); |
| pos = new PipedOutputStream(); |
| assertEquals("Test 1: Not-connected pipe returned more than zero available bytes. ", |
| 0, pis.available()); |
| |
| 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()); |
| |
| try { |
| pis.connect(pos); |
| fail("Test 3: IOException expected when reconnecting the pipe."); |
| } catch (IOException e) { |
| // Expected. |
| } |
| |
| pis.close(); |
| pos.close(); |
| } |
| |
| /** |
| * @tests java.io.PipedInputStream#read() |
| */ |
| @TestTargetNew( |
| level = TestLevel.PARTIAL_COMPLETE, |
| notes = "", |
| method = "read", |
| args = {} |
| ) |
| 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.start(); |
| |
| synchronized (pw) { |
| pw.wait(5000); |
| } |
| 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. |
| } |
| } |
| |
| /** |
| * @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(); |
| |
| synchronized (pwriter) { |
| pwriter.wait(5000); |
| } |
| pis.read(); |
| assertEquals("Test 1: No more data indication expected. ", -1, pis.read()); |
| pwriter.keepRunning = false; |
| |
| pis.close(); |
| } |
| |
| /** |
| * @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()); |
| 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. |
| } |
| } |
| |
| /** |
| * @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."); |
| } catch (IndexOutOfBoundsException t) { |
| assertEquals( |
| "IndexOutOfBoundsException rather than a subclass expected.", |
| IndexOutOfBoundsException.class, t.getClass()); |
| } |
| } |
| |
| /** |
| * @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)); |
| } |
| 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)); |
| } |
| } |
| |
| /** |
| * @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(); |
| |
| // test if writer recognizes dead reader |
| pis.connect(pos); |
| class WriteRunnable implements Runnable { |
| |
| boolean pass = false; |
| |
| boolean readerAlive = true; |
| |
| public void run() { |
| try { |
| pos.write(1); |
| while (readerAlive) { |
| Thread.sleep(100); |
| } |
| try { |
| // should throw exception since reader thread |
| // is now dead |
| pos.write(1); |
| } catch (IOException e) { |
| pass = true; |
| } |
| } catch (IOException e) { |
| // ignore |
| } catch (InterruptedException e) { |
| // ignore |
| } |
| } |
| } |
| WriteRunnable writeRunnable = new WriteRunnable(); |
| Thread writeThread = new Thread(writeRunnable); |
| class ReadRunnable implements Runnable { |
| |
| boolean pass; |
| |
| public void run() { |
| try { |
| pis.read(); |
| pass = true; |
| } catch (IOException e) {} |
| } |
| } |
| ; |
| ReadRunnable readRunnable = new ReadRunnable(); |
| Thread readThread = new Thread(readRunnable); |
| writeThread.start(); |
| readThread.start(); |
| while (readThread.isAlive()) |
| ; |
| writeRunnable.readerAlive = false; |
| assertTrue("reader thread failed to read", readRunnable.pass); |
| while (writeThread.isAlive()) |
| ; |
| assertTrue("writer thread failed to recognize dead reader", |
| writeRunnable.pass); |
| |
| // attempt to write to stream after writer closed |
| pis = new PipedInputStream(); |
| pos = new PipedOutputStream(); |
| |
| pis.connect(pos); |
| class MyRunnable implements Runnable { |
| |
| boolean pass; |
| |
| public void run() { |
| try { |
| pos.write(1); |
| } catch (IOException e) { |
| pass = true; |
| } |
| } |
| } |
| MyRunnable myRun = new MyRunnable(); |
| synchronized (pis) { |
| t = new Thread(myRun); |
| // thread t will be blocked inside pos.write(1) |
| // when it tries to call the synchronized method pis.receive |
| // because we hold the monitor for object pis |
| t.start(); |
| try { |
| // wait for thread t to get to the call to pis.receive |
| Thread.sleep(100); |
| } catch (InterruptedException e) {} |
| // now we close |
| pos.close(); |
| } |
| // we have exited the synchronized block, so now thread t will make |
| // a call to pis.receive AFTER the output stream was closed, |
| // in which case an IOException should be thrown |
| while (t.isAlive()) { |
| ; |
| } |
| assertTrue( |
| "write failed to throw IOException on closed PipedOutputStream", |
| 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(); |
| } |
| } catch (Exception ignore) { |
| } |
| super.tearDown(); |
| } |
| } |