/*
* 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.channels;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.xnio.AssertReadWrite.assertReadMessage;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.xnio.ByteBufferSlicePool;
import org.xnio.ChannelListener;
import org.xnio.OptionMap;
import org.xnio.Options;
import org.xnio.Pool;
import org.xnio.Pooled;
import org.xnio.mock.ConnectedStreamChannelMock;
/**
* Test for {@link PushBacksStreamChannel}.
*
* @author <a href="mailto:flavia.rainone@jboss.com">Flavia Rainone</a>
*
*/
public class PushBackStreamChannelTestCase {
private PushBackStreamChannel channel;
private ConnectedStreamChannelMock firstChannel;
@Before
public void init() {
firstChannel = new ConnectedStreamChannelMock();
firstChannel.enableRead(true);
channel = new PushBackStreamChannel(firstChannel);
}
@Test
public void readToEmptyBuffer() throws IOException {
final ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
assertEquals(0, channel.read(emptyBuffer));
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("dummy".getBytes("UTF-8")).flip();
channel.unget(messageBuffer);
assertEquals(0, channel.read(emptyBuffer));
firstChannel.setReadData("dummy");
assertEquals(0, channel.read(emptyBuffer));
}
@Test
public void readPushedMessage() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(10);
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("new read data".getBytes("UTF-8")).flip();
assertEquals(0, channel.read(buffer));
channel.unget(messageBuffer);
assertEquals (10, channel.read(buffer));
assertReadMessage(buffer, "new read d");
buffer.clear();
assertEquals (3, channel.read(buffer));
assertReadMessage(buffer, "ata");
}
@Test
public void readFirstChannelData() throws IOException {
firstChannel.setReadData("data", "123");
final ByteBuffer buffer = ByteBuffer.allocate(15);
assertEquals(7, channel.read(buffer));
assertReadMessage(buffer, "data", "123");
}
@Test
public void readFirstChannelDataAndPushedMessage1() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(15);
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
firstChannel.setReadData("E=");
messageBuffer.getResource().put("mc".getBytes("UTF-8")).flip();
assertEquals(2, channel.read(buffer));
assertEquals(0, channel.read(buffer));
firstChannel.setReadData("2");
channel.unget(messageBuffer);
assertEquals(2, channel.read(buffer));
assertEquals(1, channel.read(buffer));
assertEquals(0, channel.read(buffer));
assertReadMessage(buffer, "E=mc2");
}
@Test
public void readFirstChannelDataAndPushedMessage2() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(15);
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
firstChannel.setReadData("E=");
messageBuffer1.getResource().put("c".getBytes("UTF-8")).flip();
messageBuffer2.getResource().put("m".getBytes("UTF-8")).flip();
assertEquals(2, channel.read(buffer));
assertEquals(0, channel.read(buffer));
firstChannel.setReadData("2");
channel.unget(messageBuffer1);
channel.unget(messageBuffer2);
assertEquals(2, channel.read(buffer));
assertEquals(1, channel.read(buffer));
assertReadMessage(buffer, "E=mc2");
}
@Test
public void readToEmptyBufferArray() throws IOException {
final ByteBuffer[] emptyBufferArray = new ByteBuffer[0];
assertEquals(0, channel.read(emptyBufferArray));
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("dummy".getBytes("UTF-8")).flip();
channel.unget(messageBuffer);
assertEquals(0, channel.read(emptyBufferArray));
firstChannel.setReadData("dummy");
assertEquals(0, channel.read(emptyBufferArray));
}
@Test
public void readPushedMessageToByteArray() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(15);
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(20, 20);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("pushed read data".getBytes("UTF-8")).flip();
assertEquals(0, channel.read(new ByteBuffer[] {buffer}));
channel.unget(messageBuffer);
assertEquals (15, channel.read(new ByteBuffer[] {buffer}));
assertReadMessage(buffer, "pushed read dat");
}
@Test
public void readFirstChannelDataToByteArray() throws IOException {
firstChannel.setReadData("data", "for", "array");
final ByteBuffer[] buffer = new ByteBuffer[] {ByteBuffer.allocate(2), ByteBuffer.allocate(2),
ByteBuffer.allocate(2), ByteBuffer.allocate(2), ByteBuffer.allocate(2), ByteBuffer.allocate(2),
ByteBuffer.allocate(2)};
assertEquals(12, channel.read(buffer));
assertReadMessage(buffer[0], "da");
assertReadMessage(buffer[1], "ta");
assertReadMessage(buffer[2], "fo");
assertReadMessage(buffer[3], "ra");
assertReadMessage(buffer[4], "rr");
assertReadMessage(buffer[5], "ay");
assertReadMessage(buffer[6]);
}
@Test
public void readFirstChannelDataAndPushedMessageToByteArray1() throws IOException {
final ByteBuffer[] buffer = new ByteBuffer[] {ByteBuffer.allocate(3), ByteBuffer.allocate(10)};
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
firstChannel.setReadData("JBoss");
messageBuffer.getResource().put("Xnio".getBytes("UTF-8")).flip();
assertEquals(5, channel.read(buffer));
assertEquals(0, channel.read(buffer));
firstChannel.setReadData("Api");
channel.unget(messageBuffer);
assertEquals(4, channel.read(buffer));
assertEquals(3, channel.read(buffer));
assertReadMessage(buffer[0], "JBo");
assertReadMessage(buffer[1], "ss", "Xnio", "Api");
}
@Test
public void readFirstChannelDataAndPushedMessageToByteArray2() throws IOException {
final ByteBuffer[] buffer = new ByteBuffer[] {ByteBuffer.allocate(3), ByteBuffer.allocate(10)};
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
firstChannel.setReadData("JBoss");
messageBuffer1.getResource().put("io".getBytes("UTF-8")).flip();
messageBuffer2.getResource().put("Xn".getBytes("UTF-8")).flip();
assertEquals(5, channel.read(buffer));
assertEquals(0, channel.read(buffer));
firstChannel.setReadData("Api");
channel.unget(messageBuffer1);
channel.unget(messageBuffer2);
assertEquals(4, channel.read(buffer));
assertEquals(3, channel.read(buffer));
assertReadMessage(buffer[0], "JBo");
assertReadMessage(buffer[1], "ss", "Xnio", "Api");
}
@Test
public void readPushedMessageToByteArrayWithOffset() throws IOException {
final ByteBuffer[] buffer = new ByteBuffer[] {null, ByteBuffer.allocate(50)};
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(50, 50);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("read data for array with offset".getBytes("UTF-8")).flip();
assertEquals(0, channel.read(buffer, 1, 1));
channel.unget(messageBuffer);
assertEquals (31, channel.read(buffer, 1, 2));
assertReadMessage(buffer[1], "read data for array with offset");
}
@Test
public void readFirstChannelDataToByteArrayWithOffset() throws IOException {
firstChannel.setReadData("read to byte array [1]");
final ByteBuffer[] buffer = new ByteBuffer[] {null, ByteBuffer.allocate(50)};
assertEquals(22, channel.read(buffer, 1, 1));
assertReadMessage(buffer[1], "read to byte array [1]");
}
@Test
public void readFirstChannelDataAndPushedMessageToByteArrayWithOffset1() throws IOException {
final ByteBuffer[] buffer = new ByteBuffer[] {ByteBuffer.allocate(20), ByteBuffer.allocate(20),
ByteBuffer.allocate(20), ByteBuffer.allocate(20)};
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(20, 20);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
firstChannel.setReadData("123456789");
messageBuffer.getResource().put("10111213141516171819".getBytes("UTF-8")).flip();
assertEquals(9, channel.read(buffer, 1, 2));
assertEquals(0, channel.read(buffer, 1, 2));
firstChannel.setReadData("20212223242526272829");
channel.unget(messageBuffer);
assertEquals(20, channel.read(buffer, 1, 2));
assertEquals(11, channel.read(buffer, 1, 2));
assertReadMessage(buffer[0]);
assertReadMessage(buffer[1], "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "1");
assertReadMessage(buffer[2], "5", "16", "17", "18", "19", "20", "21", "22", "23", "24", "2");
assertReadMessage(buffer[3]);
}
@Test
public void readFirstChannelDataAndPushedMessageToByteArrayWithOffset2() throws IOException {
final ByteBuffer[] buffer = new ByteBuffer[] {ByteBuffer.allocate(20), ByteBuffer.allocate(20),
ByteBuffer.allocate(20), ByteBuffer.allocate(20)};
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(20, 20);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
firstChannel.setReadData("123456789");
messageBuffer1.getResource().put("16171819".getBytes("UTF-8")).flip();
messageBuffer2.getResource().put("101112131415".getBytes("UTF-8")).flip();
assertEquals(9, channel.read(buffer, 1, 2));
assertEquals(0, channel.read(buffer, 1, 2));
firstChannel.setReadData("20212223242526272829");
channel.unget(messageBuffer1);
channel.unget(messageBuffer2);
assertEquals(20, channel.read(buffer, 1, 2));
assertEquals(11, channel.read(buffer, 1, 2));
assertReadMessage(buffer[0]);
assertReadMessage(buffer[1], "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "1");
assertReadMessage(buffer[2], "5", "16", "17", "18", "19", "20", "21", "22", "23", "24", "2");
assertReadMessage(buffer[3]);
}
@Test
public void transferPushedMessageToFileChannel() throws IOException {
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("pushed message".getBytes("UTF-8")).flip();
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(0, channel.transferTo(0, 6, fileChannel));
channel.unget(messageBuffer);
assertEquals (6, channel.transferTo(0, 6, fileChannel));
fileChannel.position(0);
final ByteBuffer transferedMessage = ByteBuffer.allocate(6);
assertEquals(6, fileChannel.read(transferedMessage));
assertReadMessage(transferedMessage, "pushed");
} finally {
fileChannel.close();
}
}
@Test
public void transferFirstChannelDataToFileChannel() throws IOException {
firstChannel.setReadData("data", "from", "first", "channel");
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(20, channel.transferTo(0, 30, fileChannel));
fileChannel.position(0);
final ByteBuffer transferedMessage = ByteBuffer.allocate(30);
assertEquals(20, fileChannel.read(transferedMessage));
assertReadMessage(transferedMessage, "data", "from", "first", "channel");
} finally {
fileChannel.close();
}
}
@Test
public void transferFirstChannelDataAndPushedMessageToFileChannel1() throws IOException {
firstChannel.setReadData("x");
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("nio".getBytes("UTF-8")).flip();
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(1, channel.transferTo(0, 6, fileChannel));
assertEquals(0, channel.transferTo(1, 6, fileChannel));
firstChannel.setReadData("-api");
channel.unget(messageBuffer);
assertEquals (6, channel.transferTo(1, 6, fileChannel));
assertEquals (1, channel.transferTo(7, 6, fileChannel));
fileChannel.position(0);
final ByteBuffer transferedMessage = ByteBuffer.allocate(10);
assertEquals(8, fileChannel.read(transferedMessage));
assertReadMessage(transferedMessage, "xnio-api");
} finally {
fileChannel.close();
}
}
@Test
public void transferFirstChannelDataAndPushedMessageToFileChannel2() throws IOException {
firstChannel.setReadData("x");
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
messageBuffer1.getResource().put("io".getBytes("UTF-8")).flip();
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
messageBuffer2.getResource().put("n".getBytes("UTF-8")).flip();
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(1, channel.transferTo(0, 6, fileChannel));
assertEquals(0, channel.transferTo(1, 6, fileChannel));
firstChannel.setReadData("-api");
channel.unget(messageBuffer1);
channel.unget(messageBuffer2);
assertEquals (6, channel.transferTo(1, 6, fileChannel));
assertEquals (1, channel.transferTo(7, 6, fileChannel));
fileChannel.position(0);
final ByteBuffer transferedMessage = ByteBuffer.allocate(10);
assertEquals(8, fileChannel.read(transferedMessage));
assertReadMessage(transferedMessage, "xnio-api");
} finally {
fileChannel.close();
}
}
@Test
public void transferToStreamSinkChannel() throws Exception {
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("pushed message".getBytes("UTF-8")).flip();
final ConnectedStreamChannelMock sinkChannel = new ConnectedStreamChannelMock();
assertEquals(0, channel.transferTo(15, ByteBuffer.allocate(60), sinkChannel));
channel.unget(messageBuffer);
assertEquals(14, channel.transferTo(15, ByteBuffer.allocate(60), sinkChannel));
assertReadMessage(sinkChannel.getWrittenBytes(), "pushed", " ", "message");
}
@Test
public void transferFirstChannelDataToSinkChannel() throws IOException {
firstChannel.setReadData("data!", "from@", "first#", "channel$");
final ConnectedStreamChannelMock sinkChannel = new ConnectedStreamChannelMock();
assertEquals(24, channel.transferTo(30, ByteBuffer.allocate(60), sinkChannel));
assertReadMessage(sinkChannel.getWrittenBytes(), "data!", "from@", "first#", "channel$");
}
@Test
public void transferFirstChannelDataAndPushedMessageToSinkChannel1() throws IOException {
firstChannel.setReadData("1+");
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("2=".getBytes("UTF-8")).flip();
final ConnectedStreamChannelMock sinkChannel = new ConnectedStreamChannelMock();
final ByteBuffer throughBuffer = ByteBuffer.allocate(10);
assertEquals(1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals(1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals(0, channel.transferTo(1, throughBuffer, sinkChannel));
firstChannel.setReadData("3");
channel.unget(messageBuffer);
assertEquals (1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals (1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals (1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals (0, channel.transferTo(1, throughBuffer, sinkChannel));
assertReadMessage(sinkChannel.getWrittenBytes(), "1+2=3");
}
@Test
public void transferFirstChannelDataAndPushedMessageToSinkChannel2() throws IOException {
firstChannel.setReadData("1+");
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
messageBuffer1.getResource().put("30".getBytes("UTF-8")).flip();
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
messageBuffer2.getResource().put("2+".getBytes("UTF-8")).flip();
final ConnectedStreamChannelMock sinkChannel = new ConnectedStreamChannelMock();
final ByteBuffer throughBuffer = ByteBuffer.allocate(10);
assertEquals(1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals(1, channel.transferTo(1, throughBuffer, sinkChannel));
assertEquals(0, channel.transferTo(1, throughBuffer, sinkChannel));
firstChannel.setReadData("=33");
channel.unget(messageBuffer1);
channel.unget(messageBuffer2);
assertEquals (3, channel.transferTo(3, throughBuffer, sinkChannel));
assertEquals (3, channel.transferTo(3, throughBuffer, sinkChannel));
assertEquals (1, channel.transferTo(3, throughBuffer, sinkChannel));
assertEquals (0, channel.transferTo(3, throughBuffer, sinkChannel));
assertReadMessage(sinkChannel.getWrittenBytes(), "1+2+30=33");
}
@Test
public void suspendResumeReads() throws Exception {
channel.resumeReads();
assertTrue(firstChannel.isReadResumed());
Thread t = new Thread(new Runnable() {
public void run() {
firstChannel.setReadData("test");
}
});
t.start();
channel.awaitReadable();
t.join();
channel.suspendReads();
assertFalse(firstChannel.isReadResumed());
t = new Thread(new Runnable() {
public void run() {
channel.resumeReads();
}
});
t.start();
channel.awaitReadable(10, TimeUnit.SECONDS);
t.join();
// push data
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(15, 15);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
messageBuffer.getResource().put("pushed message".getBytes("UTF-8")).flip();
channel.unget(messageBuffer);
channel.resumeReads();
assertTrue(firstChannel.isReadResumed());
channel.awaitReadable();
channel.suspendReads();
assertFalse(firstChannel.isReadResumed());
channel.awaitReadable(10, TimeUnit.DAYS);
}
@Test
public void shutdownReads() throws IOException {
channel.shutdownReads();
assertTrue(firstChannel.isShutdownReads());
// shutdownReads is idempotent
channel.shutdownReads();
assertTrue(firstChannel.isShutdownReads());
// cannot unget after shutdown
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
boolean bufferCleared = false;
messageBuffer.getResource().put("a".getBytes("UTF-8")).flip();
channel.unget(messageBuffer);
try {
messageBuffer.getResource();
} catch (IllegalStateException e) {
bufferCleared = true;
}
assertTrue(bufferCleared);
// cannot read
final ByteBuffer buffer = ByteBuffer.allocate(30);
assertEquals(-1, channel.read(buffer));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}, 0, 1));
// cannot transfer
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(0, channel.transferTo(0, 10, null));
} finally {
fileChannel.close();
}
assertEquals(-1L, channel.transferTo(10, ByteBuffer.allocate(10), new ConnectedStreamChannelMock()));
}
@Test
public void shutdownReadsWithPushedData() throws IOException {
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
messageBuffer1.getResource().put("1".getBytes("UTF-8")).flip();
channel.unget(messageBuffer1);
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
messageBuffer2.getResource().put("2".getBytes("UTF-8")).flip();
channel.unget(messageBuffer2);
channel.shutdownReads();
assertTrue(firstChannel.isShutdownReads());
// shutdownReads is idempotent
channel.shutdownReads();
assertTrue(firstChannel.isShutdownReads());
// cannot unget after shutdown
final Pooled<ByteBuffer> messageBuffer3 = messagePool.allocate();
boolean bufferCleared = false;
messageBuffer3.getResource().put("3".getBytes("UTF-8")).flip();
channel.unget(messageBuffer3);
try {
messageBuffer3.getResource();
} catch (IllegalStateException e) {
bufferCleared = true;
}
assertTrue(bufferCleared);
// cannot read
final ByteBuffer buffer = ByteBuffer.allocate(30);
assertEquals(-1, channel.read(buffer));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}, 0, 1));
// cannot transfer
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(0, channel.transferTo(0, 10, null));
} finally {
fileChannel.close();
}
assertEquals(-1L, channel.transferTo(10, ByteBuffer.allocate(10), new ConnectedStreamChannelMock()));
}
@Test
public void closeEmptyChannel() throws IOException {
channel.close();
assertFalse(channel.isOpen());
assertFalse(firstChannel.isOpen());
// close is idempotent
channel.close();
assertFalse(channel.isOpen());
assertFalse(firstChannel.isOpen());
// close is idempotent
channel.close();
assertFalse(channel.isOpen());
assertFalse(firstChannel.isOpen());
// cannot unget after closed
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer = messagePool.allocate();
boolean bufferCleared = false;
messageBuffer.getResource().put("a".getBytes("UTF-8")).flip();
channel.unget(messageBuffer);
try {
messageBuffer.getResource();
} catch (IllegalStateException e) {
bufferCleared = true;
}
assertTrue(bufferCleared);
// cannot read
final ByteBuffer buffer = ByteBuffer.allocate(30);
assertEquals(-1, channel.read(buffer));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}, 0, 1));
// cannot transfer
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(0, channel.transferTo(0, 10, null));
} finally {
fileChannel.close();
}
assertEquals(-1L, channel.transferTo(10, ByteBuffer.allocate(10), new ConnectedStreamChannelMock()));
// await readable does nothing
channel.awaitReadable();
channel.awaitReadable(1, TimeUnit.DAYS);
}
@Test
public void closeChannelWithPushedData() throws IOException {
final Pool<ByteBuffer> messagePool = new ByteBufferSlicePool(5, 5);
final Pooled<ByteBuffer> messageBuffer1 = messagePool.allocate();
messageBuffer1.getResource().put("1".getBytes("UTF-8")).flip();
channel.unget(messageBuffer1);
final Pooled<ByteBuffer> messageBuffer2 = messagePool.allocate();
messageBuffer2.getResource().put("2".getBytes("UTF-8")).flip();
channel.unget(messageBuffer2);
channel.close();
assertFalse(channel.isOpen());
assertFalse(firstChannel.isOpen());
// close is idempotent
channel.close();
assertFalse(channel.isOpen());
assertFalse(firstChannel.isOpen());
// cannot unget after closed
final Pooled<ByteBuffer> messageBuffer3 = messagePool.allocate();
boolean bufferCleared = false;
messageBuffer3.getResource().put("3".getBytes("UTF-8")).flip();
channel.unget(messageBuffer3);
try {
messageBuffer3.getResource();
} catch (IllegalStateException e) {
bufferCleared = true;
}
assertTrue(bufferCleared);
// cannot read
final ByteBuffer buffer = ByteBuffer.allocate(30);
assertEquals(-1, channel.read(buffer));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}));
assertEquals(-1, channel.read(new ByteBuffer[] {buffer}, 0, 1));
// cannot transfer
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
final FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
try {
assertEquals(0, channel.transferTo(0, 10, null));
} finally {
fileChannel.close();
}
assertEquals(-1L, channel.transferTo(10, ByteBuffer.allocate(10), new ConnectedStreamChannelMock()));
// await readable does nothing
channel.awaitReadable();
channel.awaitReadable(1, TimeUnit.DAYS);
}
@Test
public void delegateOperationsToFirstChannel() throws IOException {
assertSame(firstChannel, channel.getChannel());
channel.resumeReads();
assertTrue(firstChannel.isReadResumed());
assertTrue(channel.isReadResumed());
channel.suspendReads();
assertFalse(firstChannel.isReadResumed());
assertFalse(channel.isReadResumed());
channel.wakeupReads();
assertTrue(firstChannel.isReadAwaken());
assertTrue(channel.isReadResumed());
assertSame(firstChannel.getReadThread(), channel.getReadThread());
assertSame(firstChannel.getWorker(), channel.getWorker());
assertSame(firstChannel.isOpen(), channel.isOpen());
firstChannel.setOptionMap(OptionMap.create(Options.KEEP_ALIVE, true, Options.READ_TIMEOUT, 3000));
assertSame(firstChannel.supportsOption(Options.BACKLOG), channel.supportsOption(Options.BACKLOG));
assertSame(firstChannel.supportsOption(Options.KEEP_ALIVE), channel.supportsOption(Options.KEEP_ALIVE));
assertSame(firstChannel.supportsOption(Options.READ_TIMEOUT), channel.supportsOption(Options.READ_TIMEOUT));
assertSame(firstChannel.getOption(Options.BACKLOG), channel.getOption(Options.BACKLOG));
assertSame(firstChannel.getOption(Options.KEEP_ALIVE), channel.getOption(Options.KEEP_ALIVE));
assertSame(firstChannel.getOption(Options.READ_TIMEOUT), channel.getOption(Options.READ_TIMEOUT));
channel.setOption(Options.BACKLOG, 5000);
assertEquals(5000, (int) firstChannel.getOption(Options.BACKLOG));
assertEquals(5000, (int) channel.getOption(Options.BACKLOG));
}
@Test
public void getListenerSetter() {
final DummyListener readListener = new DummyListener();
final DummyListener closeListener = new DummyListener();
channel.getReadSetter().set(readListener);
channel.getCloseSetter().set(closeListener);
assertFalse(readListener.isInvoked());
firstChannel.getReadListener().handleEvent(firstChannel);
assertTrue(readListener.isInvoked());
assertFalse(closeListener.isInvoked());
firstChannel.getCloseListener().handleEvent(firstChannel);
assertTrue(closeListener.isInvoked());
}
private static class DummyListener implements ChannelListener<PushBackStreamChannel> {
private boolean invoked = false;
@Override
public void handleEvent(PushBackStreamChannel channel) {
invoked = true;
}
public boolean isInvoked() {
return invoked;
}
};
}