/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2012 Red Hat, Inc. and/or its affiliates, and individual
* contributors as indicated by the @author tags.
*
* Licensed 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.xnio.streams;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.xnio.AssertReadWrite.assertReadMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import org.junit.Test;
/**
* Test for {@link Pipe}.
*
* @author <a href="mailto:flavia.rainone@jboss.com">Flavia Rainone</a>
*/
public class PipeTestCase {
@Test
public void readAndWriteBytes() throws IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write('a');
assertEquals('a', inputStream.read());
close(outputStream);
close(inputStream);
}
@Test
public void readAndWriteByteArray() throws IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write("array".getBytes());
byte[] bytes = new byte[10];
assertEquals(5, inputStream.read(bytes));
assertReadMessage(bytes, "array");
close(outputStream);
close(inputStream);
}
@Test
public void readAndWriteBytesWithBufferOverflow() throws IOException {
final Pipe pipe = new Pipe(3);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write('a');
outputStream.write('b');
outputStream.write('c');
assertEquals('a', inputStream.read());
assertEquals('b', inputStream.read());
assertEquals('c', inputStream.read());
outputStream.write('d');
outputStream.write('e');
outputStream.write('f');
assertEquals('d', inputStream.read());
assertEquals('e', inputStream.read());
assertEquals('f', inputStream.read());
close(outputStream);
close(inputStream);
}
@Test
public void readAndWriteByteArrayWithBufferOverflow() throws IOException {
final Pipe pipe = new Pipe(3);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write("abc".getBytes());
byte[] bytes = new byte[10];
assertEquals(3, inputStream.read(bytes));
assertReadMessage(bytes, "abc");
outputStream.write("def".getBytes());
inputStream.read(bytes, 3, 3);
assertReadMessage(bytes, "abc", "def");
close(outputStream);
close(inputStream);
}
@Test
public void readByteFromClosedStream() throws IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write('a');
close(outputStream);
assertEquals('a', inputStream.read());
assertEquals(-1, inputStream.read());
close(inputStream);
}
@Test
public void readByteArrayFromClosedStream() throws IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
assertNotNull(inputStream);
assertNotNull(inputStream.toString());
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
outputStream.write('a');
close(outputStream);
byte[] bytes = new byte[5];
assertEquals(1, inputStream.read(bytes));
assertEquals('a', bytes[0]);
assertEquals(-1, inputStream.read(bytes, 1, 4));
close(inputStream);
}
@Test
public void readFromEmptyClosedStream() throws IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
assertNotNull(outputStream);
assertNotNull(outputStream.toString());
close(outputStream);
assertEquals(-1, inputStream.read());
assertEquals(-1, inputStream.read(new byte[3]));
close(inputStream);
}
@Test
public void readByteBlocksUntilWrite() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
final ReadByteTask readTask = new ReadByteTask(inputStream);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.write('b');
readThread.join();
assertEquals('b', readTask.getReadResult());
}
@Test
public void readByteArrayBlocksUntilWrite1() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
byte[] bytes = new byte[5];
final ReadByteArrayTask readTask = new ReadByteArrayTask(inputStream, bytes);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.write("block".getBytes());
readThread.join();
assertEquals(5, readTask.getReadResult());
assertReadMessage(bytes, "block");
}
@Test
public void readByteArrayBlocksUntilWrite2() throws Exception {
final Pipe pipe = new Pipe(10);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
byte[] bytes1 = new byte[15];
byte[] bytes2 = new byte[15];
final ReadByteArrayTask readTask1 = new ReadByteArrayTask(inputStream, bytes1);
final ReadByteArrayTask readTask2 = new ReadByteArrayTask(inputStream, bytes2);
final Thread readThread1 = new Thread(readTask1);
final Thread readThread2 = new Thread(readTask2);
readThread1.start();
readThread1.join(200);
readThread2.start();
readThread2.join(200);
assertTrue(readThread1.isAlive());
assertTrue(readThread2.isAlive());
outputStream.write("abcdefghij".getBytes());
outputStream.write("klmnopqrst".getBytes());
readThread1.join();
readThread2.join();
outputStream.write("klmnopqrst".getBytes());
assertEquals(10, readTask1.getReadResult());
if (bytes1[0] == 'a') {
assertReadMessage(bytes1, "abcdefghij");
assertReadMessage(bytes2, "klmnopqrst");
} else {
assertReadMessage(bytes1, "klmnopqrst");
assertReadMessage(bytes2, "abcdefghij");
}
}
@Test
public void readBytesBlocksUntilCloseOutput() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
final ReadByteTask readTask = new ReadByteTask(inputStream);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.close();
readThread.join();
assertEquals(-1, readTask.getReadResult());
}
@Test
public void readByteArrayBlocksUntilCloseOutput() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
byte[] bytes = new byte[5];
final ReadByteArrayTask readTask = new ReadByteArrayTask(inputStream, bytes);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.close();
readThread.join();
assertEquals(-1, readTask.getReadResult());
}
@Test
public void readBytesBlocksUntilWriteAndCloseOutput() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
final ReadByteTask readTask = new ReadByteTask(inputStream);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.write('a');
outputStream.close();
readThread.join();
assertEquals('a', readTask.getReadResult());
assertEquals(-1, inputStream.read());
}
@Test
public void readByteArrayBlocksUntilWriteAndCloseOutput() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
byte[] bytes = new byte[5];
final ReadByteArrayTask readTask = new ReadByteArrayTask(inputStream, bytes);
final Thread readThread = new Thread(readTask);
readThread.start();
readThread.join(200);
assertTrue(readThread.isAlive());
outputStream.write('a');
outputStream.close();
readThread.join();
assertEquals(1, readTask.getReadResult());
assertReadMessage(bytes, "a");
assertEquals(-1, inputStream.read(bytes));
}
@Test
public void readBlocksUntilCloseInput() throws Exception {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final ReadByteTask readTask1 = new ReadByteTask(inputStream);
final ReadByteArrayTask readTask2 = new ReadByteArrayTask(inputStream, new byte[3]);
final Thread readThread1 = new Thread(readTask1);
final Thread readThread2 = new Thread(readTask2);
readThread1.start();
readThread2.start();
readThread1.join(200);
assertTrue(readThread1.isAlive());
readThread2.join(200);
assertTrue(readThread2.isAlive());
inputStream.close();
readThread1.join();
readThread2.join();
assertEquals(-1, readTask1.getReadResult());
assertEquals(-1, readTask2.getReadResult());
}
@Test
public void writeByteBlocksUntilRead() throws Exception {
final Pipe pipe = new Pipe(5);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write("input".getBytes());
final WriteByteTask writeTask = new WriteByteTask(outputStream, (byte) '0');
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
assertEquals('i', inputStream.read());
writeThread.join();
assertNull(writeTask.getWriteException());
assertEquals('n', inputStream.read());
assertEquals('p', inputStream.read());
assertEquals('u', inputStream.read());
assertEquals('t', inputStream.read());
assertEquals('0', inputStream.read());
close(inputStream);
close(outputStream);
}
@Test
public void writeByteArrayBlocksUntilRead() throws Exception {
final Pipe pipe = new Pipe(5);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write("12345".getBytes());
final WriteByteArrayTask writeTask = new WriteByteArrayTask(outputStream, "67890".getBytes());
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
assertEquals('1', inputStream.read());
assertEquals('2', inputStream.read());
final byte[] bytes = new byte[5];
int read = inputStream.read(bytes);
writeThread.join();
assertNull(writeTask.getWriteException());
assertReadMessage(bytes, "34567".substring(0, read)); // assert we actually got the amount of bytes returned by read operation
switch (read) {
case 0:
assertEquals('3', inputStream.read());
case 1:
assertEquals('4', inputStream.read());
case 2:
assertEquals('5', inputStream.read());
case 3:
assertEquals('6', inputStream.read());
case 4:
assertEquals('7', inputStream.read());
break;
default:
assertFalse("Should've read up to 5 bytes into 5-length bytes array, but read: " + read, read > 5);
}
assertEquals('8', inputStream.read());
assertEquals('9', inputStream.read());
assertEquals('0', inputStream.read());
close(inputStream);
close(outputStream);
}
@Test
public void writeByteBlocksUntilCloseInput() throws Exception {
final Pipe pipe = new Pipe(1);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write('1');
final WriteByteTask writeTask = new WriteByteTask(outputStream, (byte) '2');
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
close(inputStream);
writeThread.join();
assertNotNull(writeTask.getWriteException());
assertEquals(-1, inputStream.read());
}
@Test
public void writeByteArrayBlocksUntilCloseInput() throws Exception {
final Pipe pipe = new Pipe(1);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write('1');
final WriteByteArrayTask writeTask = new WriteByteArrayTask(outputStream, "2".getBytes());
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
close(inputStream);
writeThread.join();
assertNotNull(writeTask.getWriteException());
assertEquals(-1, inputStream.read());
}
@Test
public void writeByteBlocksUntilCloseOutput() throws Exception {
final Pipe pipe = new Pipe(3);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write("123".getBytes());
final WriteByteTask writeTask = new WriteByteTask(outputStream, (byte) '4');
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
close(outputStream);
writeThread.join();
assertNotNull(writeTask.getWriteException());
final byte[] bytes = new byte[5];
assertEquals(3, inputStream.read(bytes));
assertReadMessage(bytes, "123");
}
@Test
public void writeByteArrayBlocksUntilCloseOutput() throws Exception {
final Pipe pipe = new Pipe(3);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write("123".getBytes());
final WriteByteArrayTask writeTask = new WriteByteArrayTask(outputStream, "45".getBytes());
final Thread writeThread = new Thread(writeTask);
writeThread.start();
writeThread.join(200);
assertTrue(writeThread.isAlive());
close(outputStream);
writeThread.join();
assertNotNull(writeTask.getWriteException());
final byte[] bytes = new byte[5];
assertEquals(3, inputStream.read(bytes));
assertReadMessage(bytes, "123");
}
@Test
public void awaitReadCloses() throws Exception {
final Pipe pipe = new Pipe(100);
final Thread awaitThread = new Thread(new AwaitTask(pipe));
awaitThread.start();
awaitThread.join(200);
assertTrue(awaitThread.isAlive());
close(pipe.getIn());
awaitThread.join();
}
@Test
public void awaitReadClosesAfterWriteCloses() throws Exception {
final Pipe pipe = new Pipe(100);
final Thread awaitThread = new Thread(new AwaitTask(pipe));
awaitThread.start();
awaitThread.join(200);
assertTrue(awaitThread.isAlive());
close(pipe.getOut());
awaitThread.join(200);
assertTrue(awaitThread.isAlive());
close(pipe.getIn());
awaitThread.join();
}
@Test
public void wrappedBytes() throws IOException {
final Pipe pipe = new Pipe(10);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
outputStream.write("12345".getBytes());
byte[] bytes = new byte[20];
assertEquals(5, inputStream.read(bytes));
assertReadMessage(bytes, "12345");
outputStream.write("6789012345".getBytes());
assertEquals(10, inputStream.read(bytes, 5, 15));
assertReadMessage(bytes, "12345", "67890", "12345");
outputStream.write("12345678".getBytes());
assertEquals(0, inputStream.read(bytes, 15, 0));
assertEquals(5, inputStream.read(bytes, 15, 5));
assertReadMessage(bytes, "12345", "67890", "12345", "12345");
assertEquals('6', inputStream.read());
assertEquals('7', inputStream.read());
assertEquals('8', inputStream.read());
outputStream.write("9012345".getBytes());
outputStream.write("678".getBytes());
assertEquals(10, inputStream.read(bytes));
outputStream.write("0123456".getBytes());
assertEquals(5, inputStream.read(bytes, 10, 5));
assertReadMessage(bytes, "9012345", "678", "01234");
outputStream.write("7890123".getBytes());
assertEquals(9, inputStream.read(bytes));
assertReadMessage(bytes, "56", "7890123");
}
@Test
public void closeOnlyInputStream() throws UnsupportedEncodingException, IOException {
final Pipe pipe = new Pipe(100);
final InputStream inputStream = pipe.getIn();
final OutputStream outputStream = pipe.getOut();
close(inputStream);
IOException expected = null;
try {
outputStream.write("abc".getBytes("UTF-8"));
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
assertEquals(-1, inputStream.read());
assertEquals(-1, inputStream.read(new byte[1]));
}
private void close(OutputStream stream) throws IOException {
stream.close();
IOException expected = null;
try {
stream.write('a');
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
expected = null;
try {
stream.write("abc".getBytes("UTF-8"));
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
expected = null;
try {
stream.write("#@abc#$%^".getBytes("UTF-8"), 2, 3);
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
// close must be idempotent
stream.close();
expected = null;
try {
stream.write('a');
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
expected = null;
try {
stream.write("abc".getBytes("UTF-8"));
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
expected = null;
try {
stream.write("#@abc#$%^".getBytes("UTF-8"), 2, 3);
} catch (IOException e) {
expected = e;
}
assertNotNull(expected);
}
private void close(InputStream stream) throws IOException {
stream.close();
assertEquals(-1, stream.read());
assertEquals(-1, stream.read(new byte[10]));
assertEquals(-1, stream.read(new byte[10], 1, 7));
// close must be idempotent
stream.close();
assertEquals(-1, stream.read());
assertEquals(-1, stream.read(new byte[10]));
assertEquals(-1, stream.read(new byte[10], 1, 7));
}
private static class ReadByteTask implements Runnable {
private final InputStream stream;
private int readResult;
public ReadByteTask(InputStream s) {
stream = s;
}
@Override
public void run() {
try {
readResult = stream.read();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public int getReadResult() {
return readResult;
}
}
private static class ReadByteArrayTask implements Runnable {
private final InputStream stream;
private final byte[] bytes;
private int readResult;
public ReadByteArrayTask(InputStream s, byte[] b) {
stream = s;
bytes = b;
}
@Override
public void run() {
try {
readResult = stream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public int getReadResult() {
return readResult;
}
}
private static class WriteByteTask implements Runnable {
private final OutputStream stream;
private final byte writeByte;
private IOException exception;
public WriteByteTask(OutputStream s, byte b) {
stream = s;
writeByte = b;
}
@Override
public void run() {
try {
stream.write(writeByte);
} catch (IOException e) {
exception = e;
}
}
public IOException getWriteException() {
return exception;
}
}
private static class WriteByteArrayTask implements Runnable {
private final OutputStream stream;
private final byte[] bytes;
private IOException exception;
public WriteByteArrayTask(OutputStream s, byte[] b) {
stream = s;
bytes = b;
}
@Override
public void run() {
try {
stream.write(bytes);
} catch (IOException e) {
exception = e;
}
}
public IOException getWriteException() {
return exception;
}
}
private static class AwaitTask implements Runnable {
private final Pipe pipe;
public AwaitTask(Pipe p) {
pipe = p;
}
@Override
public void run() {
pipe.await();
}
}
}