blob: 671bfe9199ab0cad71ddbcd97c1faf9130612b7a [file] [log] [blame]
/*
* 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();
}
}