/* * 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; } }; }