/* * JBoss, Home of Professional Open Source. * * Copyright 2013 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; 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.assertSame; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.Channel; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; import org.xnio.channels.AcceptingChannel; import org.xnio.channels.AssembledConnectedMessageChannel; import org.xnio.channels.AssembledConnectedStreamChannel; import org.xnio.channels.BoundChannel; import org.xnio.channels.ConnectedMessageChannel; import org.xnio.channels.ConnectedStreamChannel; import org.xnio.channels.MulticastMessageChannel; import org.xnio.management.XnioServerMXBean; import org.xnio.management.XnioWorkerMXBean; import org.xnio.mock.AcceptingChannelMock; import org.xnio.mock.MessageConnectionMock; import org.xnio.mock.Mock; import org.xnio.mock.MulticastMessageChannelMock; import org.xnio.mock.StreamConnectionMock; import org.xnio.mock.XnioIoThreadMock; import org.xnio.mock.XnioWorkerMock; /** * Test for {@link XnioWorker}. * * @author <a href="mailto:frainone@redhat.com">Flavia Rainone</a> * */ @SuppressWarnings("deprecation") public class XnioWorkerTestCase { private static final SocketAddress unknownSocketAddress = new SocketAddress() {private static final long serialVersionUID = 1L;}; private XnioWorker xnioWorker; @Before public void init() throws IllegalArgumentException, IOException { final Xnio xnio = Xnio.getInstance(); xnioWorker = xnio.createWorker(OptionMap.create(Options.WORKER_NAME, "worker for tests", Options.THREAD_DAEMON, true)); assertNotNull(xnioWorker); assertEquals("worker for tests", xnioWorker.getName()); } private void checkCreateStreamServer(SocketAddress socketAddress, String channelInfo) throws IOException { final TestChannelListener<AcceptingChannel<ConnectedStreamChannel>> acceptingChannelListener = new TestChannelListener<AcceptingChannel<ConnectedStreamChannel>>();; final OptionMap optionMap = OptionMap.create(Options.BROADCAST, true); // use any option, for test purposes final AcceptingChannel<? extends ConnectedStreamChannel> streamServer = xnioWorker.createStreamServer( socketAddress, acceptingChannelListener, optionMap); assertNotNull(streamServer); assertEquals(socketAddress, streamServer.getLocalAddress()); assertEquals(socketAddress, streamServer.getLocalAddress(socketAddress.getClass())); assertNotNull(streamServer.getIoThread()); assertSame(xnioWorker, streamServer.getWorker()); // make sure that acceptance is being delegated to AcceptingChannelMock final AssembledConnectedStreamChannel assembledChannel = (AssembledConnectedStreamChannel) streamServer.accept(); assertNotNull(assembledChannel); // check that acceptance has been correctly delegated to XnioWorkerMock final StreamConnectionMock connection = getConnectedChannel(assembledChannel); assertNotNull(connection); assertSame(streamServer, acceptingChannelListener.getChannel()); assertEquals(optionMap, connection.getOptionMap()); assertEquals(channelInfo, connection.getInfo()); // retrieve actual accepting channel final AcceptingChannelMock acceptingChannel = connection.getServer(); assertEquals(optionMap, acceptingChannel.getOptionMap()); assertEquals(channelInfo, acceptingChannel.getInfo()); assertEquals(socketAddress, acceptingChannel.getLocalAddress()); assertEquals(socketAddress, acceptingChannel.getLocalAddress(socketAddress.getClass())); // check correct delegation between the stream server and actual accepting channel assertFalse(acceptingChannel.isAcceptResumed()); streamServer.resumeAccepts(); assertTrue(acceptingChannel.isAcceptResumed()); streamServer.suspendAccepts(); assertFalse(acceptingChannel.isAcceptResumed()); assertFalse(acceptingChannel.isAcceptWokenUp()); streamServer.wakeupAccepts(); assertTrue(acceptingChannel.isAcceptWokenUp()); assertFalse(acceptingChannel.haveWaitedAcceptable()); streamServer.awaitAcceptable(); assertTrue(acceptingChannel.haveWaitedAcceptable()); acceptingChannel.clearWaitedAcceptable(); streamServer.awaitAcceptable(10, TimeUnit.MILLISECONDS); assertTrue(acceptingChannel.haveWaitedAcceptable()); assertEquals(10, acceptingChannel.getAwaitAcceptableTime()); assertSame(TimeUnit.MILLISECONDS, acceptingChannel.getAwaitAcceptableTimeUnit()); assertSame(acceptingChannel.getAcceptThread(), streamServer.getAcceptThread()); acceptingChannel.setSupportedOptions(Options.KEEP_ALIVE); // use any option, just for testing purposes assertTrue(streamServer.supportsOption(Options.KEEP_ALIVE)); assertFalse(streamServer.supportsOption(Options.BROADCAST)); assertTrue(streamServer.getOption(Options.BROADCAST)); assertTrue(acceptingChannel.getOption(Options.BROADCAST)); assertTrue(streamServer.setOption(Options.BROADCAST, false)); assertFalse(streamServer.getOption(Options.BROADCAST)); assertFalse(acceptingChannel.getOption(Options.BROADCAST)); assertTrue(streamServer.isOpen()); assertTrue(acceptingChannel.isOpen()); streamServer.close(); assertFalse(streamServer.isOpen()); assertFalse(acceptingChannel.isOpen()); ((XnioWorkerMock) xnioWorker).failConnection(); final AcceptingChannel<? extends ConnectedStreamChannel> failAcceptanceServer = xnioWorker.createStreamServer(socketAddress, acceptingChannelListener, optionMap); assertNull(failAcceptanceServer.accept()); } @Test public void createTcpStreamServer() throws IOException { checkCreateStreamServer(new InetSocketAddress(1000), XnioWorkerMock.TCP_CHANNEL_INFO); } @Test public void createLocalStreamServer() throws IOException { checkCreateStreamServer(new LocalSocketAddress("server"), XnioWorkerMock.LOCAL_CHANNEL_INFO); } @Test public void createStreamServerWithInvalidAddress() throws IOException { final ChannelListener<? super AcceptingChannel<ConnectedStreamChannel>> acceptingChannelListener = new ChannelListener<AcceptingChannel<ConnectedStreamChannel>>() { @Override public void handleEvent(AcceptingChannel<ConnectedStreamChannel> channel) {} }; Exception expected = null; try { xnioWorker.createStreamServer(null, acceptingChannelListener, OptionMap.create(Options.BROADCAST, true)); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.createStreamServer(new SocketAddress() {private static final long serialVersionUID = 1L;}, acceptingChannelListener, OptionMap.create(Options.BROADCAST, true)); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); } private void checkConnectStream(SocketAddress socketAddress, SocketAddress localSocketAddress, String channelInfo) throws CancellationException, IOException { final TestChannelListener<ConnectedStreamChannel> channelListener = new TestChannelListener<ConnectedStreamChannel>(); final OptionMap optionMap = OptionMap.create(Options.MAX_INBOUND_MESSAGE_SIZE, 50000); final IoFuture<ConnectedStreamChannel> connectedStreamChannel = xnioWorker.connectStream(socketAddress, channelListener, optionMap); assertNotNull(connectedStreamChannel); final AssembledConnectedStreamChannel assembledChannel = (AssembledConnectedStreamChannel) connectedStreamChannel.get(); assertNotNull(assembledChannel); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); assertEquals(localSocketAddress, assembledChannel.getLocalAddress()); assertEquals(socketAddress, assembledChannel.getPeerAddress()); } @Test public void connectTcpStream() throws CancellationException, IOException { checkConnectStream(new InetSocketAddress(1000), Xnio.ANY_INET_ADDRESS, XnioWorkerMock.TCP_CHANNEL_INFO); } @Test public void connectLocalStream() throws CancellationException, IOException { checkConnectStream(new LocalSocketAddress("server for test"), Xnio.ANY_LOCAL_ADDRESS, XnioWorkerMock.LOCAL_CHANNEL_INFO); } private void checkConnectStreamWithBindListener(SocketAddress socketAddress, SocketAddress localSocketAddress, String channelInfo) throws CancellationException, IOException { final TestChannelListener<ConnectedStreamChannel> channelListener = new TestChannelListener<ConnectedStreamChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final OptionMap optionMap = OptionMap.create(Options.MAX_OUTBOUND_MESSAGE_SIZE, 50000); final IoFuture<ConnectedStreamChannel> connectedStreamChannel = xnioWorker.connectStream(socketAddress, channelListener, bindListener, optionMap); assertNotNull(connectedStreamChannel); final AssembledConnectedStreamChannel assembledConnectionStream = (AssembledConnectedStreamChannel) connectedStreamChannel.get(); assertNotNull(assembledConnectionStream); final StreamConnectionMock connection = getConnectedChannel(assembledConnectionStream); assertNotNull(connection); assertTrue(channelListener.isInvoked()); assertSame(assembledConnectionStream, channelListener.getChannel()); assertTrue(bindListener.isInvoked()); assertSame(connection, bindListener.getChannel()); assertEquals(localSocketAddress, connection.getLocalAddress()); assertEquals(socketAddress, connection.getPeerAddress()); assertEquals(optionMap, connection.getOptionMap()); assertEquals(channelInfo, connection.getInfo()); } @Test public void connectTcpStreamWithBindListener() throws CancellationException, IOException { checkConnectStreamWithBindListener(new InetSocketAddress(1500), Xnio.ANY_INET_ADDRESS, XnioWorkerMock.TCP_CHANNEL_INFO); } @Test public void connectLocalStreamWithBindListener() throws CancellationException, IOException { checkConnectStreamWithBindListener(new LocalSocketAddress("server for test"), Xnio.ANY_LOCAL_ADDRESS, XnioWorkerMock.LOCAL_CHANNEL_INFO); } @Test public void connectStreamWithInvalidAddress() { final ChannelListener<ConnectedStreamChannel> channelListener = new TestChannelListener<ConnectedStreamChannel>(); final ChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); Exception expected = null; try { xnioWorker.connectStream(null, channelListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(unknownSocketAddress, channelListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(unknownSocketAddress, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(null, new LocalSocketAddress("local"), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(new LocalSocketAddress("local"), null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(null, null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(new InetSocketAddress(800), new LocalSocketAddress("local"), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(new LocalSocketAddress("local"), new InetSocketAddress(800), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectStream(unknownSocketAddress, unknownSocketAddress, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); } private void checkConnectStreamWithBindListenerAndDestination(SocketAddress socketAddress, SocketAddress localSocketAddress, String channelInfo) throws CancellationException, IOException { final TestChannelListener<ConnectedStreamChannel> channelListener = new TestChannelListener<ConnectedStreamChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final OptionMap optionMap = OptionMap.create(Options.MAX_OUTBOUND_MESSAGE_SIZE, 50000); final IoFuture<ConnectedStreamChannel> connectedStreamChannel = xnioWorker.connectStream(localSocketAddress, socketAddress, channelListener, bindListener, optionMap); assertNotNull(connectedStreamChannel); final AssembledConnectedStreamChannel assembledChannel = (AssembledConnectedStreamChannel) connectedStreamChannel.get(); assertNotNull(assembledChannel); final StreamConnectionMock connection = getConnectedChannel(assembledChannel); assertNotNull(connection); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); assertTrue(bindListener.isInvoked()); assertSame(connection, bindListener.getChannel()); assertEquals(localSocketAddress, connection.getLocalAddress()); assertEquals(socketAddress, connection.getPeerAddress()); assertEquals(optionMap, connection.getOptionMap()); assertEquals(channelInfo, connection.getInfo()); } @Test public void connectTcpStreamWithBindListenerAndDestination() throws CancellationException, IOException { checkConnectStreamWithBindListenerAndDestination(new InetSocketAddress(1500), new InetSocketAddress(500), XnioWorkerMock.TCP_CHANNEL_INFO); } @Test public void connectLocalStreamWithBindListenerAndDestination() throws CancellationException, IOException { checkConnectStreamWithBindListenerAndDestination(new LocalSocketAddress("server for test..."), new LocalSocketAddress("one more address"), XnioWorkerMock.LOCAL_CHANNEL_INFO); } private void checkAcceptStream(SocketAddress socketAddress, String channelInfo) throws CancellationException, IOException { final TestChannelListener<ConnectedStreamChannel> channelListener = new TestChannelListener<ConnectedStreamChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final OptionMap optionMap = OptionMap.create(Options.READ_TIMEOUT, 800000); final IoFuture<ConnectedStreamChannel> connectedStreamChannel = xnioWorker.acceptStream(socketAddress, channelListener, bindListener, optionMap); assertNotNull(connectedStreamChannel); final AssembledConnectedStreamChannel assembledChannel = (AssembledConnectedStreamChannel) connectedStreamChannel.get(); assertNotNull(assembledChannel); final StreamConnectionMock connection = getConnectedChannel(assembledChannel); assertNotNull(connection); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); assertTrue(bindListener.isInvoked()); assertSame(connection, bindListener.getChannel()); assertEquals(socketAddress, connection.getPeerAddress()); assertEquals(optionMap, connection.getOptionMap()); assertEquals(channelInfo, connection.getInfo()); } @Test public void acceptTcpStream() throws CancellationException, IOException { checkAcceptStream(new InetSocketAddress(1567), XnioWorkerMock.TCP_CHANNEL_INFO); } @Test public void acceptLocalStream() throws CancellationException, IOException { checkAcceptStream(new LocalSocketAddress("local address"), XnioWorkerMock.LOCAL_CHANNEL_INFO); } @Test public void acceptStreamWithInvalidAddress() { final ChannelListener<ConnectedStreamChannel> openListener = new TestChannelListener<ConnectedStreamChannel>(); final ChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); Exception expected = null; try { xnioWorker.acceptStream(null, openListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.acceptStream(unknownSocketAddress, openListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); } @Test public void connectDatagram() throws CancellationException, IOException { final SocketAddress socketAddress = new LocalSocketAddress("local"); final TestChannelListener<ConnectedMessageChannel> channelListener = new TestChannelListener<ConnectedMessageChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final OptionMap optionMap = OptionMap.create(Options.WRITE_TIMEOUT, 800000); final IoFuture<ConnectedMessageChannel> connectedDatagramFuture = xnioWorker.connectDatagram(socketAddress, channelListener, bindListener, optionMap); assertNotNull(connectedDatagramFuture); final AssembledConnectedMessageChannel assembledChannel = (AssembledConnectedMessageChannel) connectedDatagramFuture.get(); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); //assertTrue(bindListener.isInvoked()); // FIXME XNIO-192 //assertSame(assembledChannel, bindListener.getChannel()); assertEquals(Xnio.ANY_LOCAL_ADDRESS, assembledChannel.getLocalAddress()); assertEquals(socketAddress, assembledChannel.getPeerAddress()); assertEquals(800000, (int) assembledChannel.getOption(Options.WRITE_TIMEOUT)); final MessageConnectionMock connectionMock = getConnectedChannel(assembledChannel); assertSame(optionMap, connectionMock.getOptionMap()); assertEquals(XnioWorkerMock.LOCAL_CHANNEL_INFO, connectionMock.getInfo()); } @Test public void connectDatagramWithBindAddress() throws CancellationException, IOException { final SocketAddress socketAddress = new LocalSocketAddress("local1"); final SocketAddress bindAddress = new LocalSocketAddress("local2"); final TestChannelListener<ConnectedMessageChannel> channelListener = new TestChannelListener<ConnectedMessageChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final OptionMap optionMap = OptionMap.create(Options.STACK_SIZE, 9000000l); final IoFuture<ConnectedMessageChannel> connectedDatagramFuture = xnioWorker.connectDatagram(bindAddress, socketAddress, channelListener, bindListener, optionMap); assertNotNull(connectedDatagramFuture); final AssembledConnectedMessageChannel assembledChannel = (AssembledConnectedMessageChannel) connectedDatagramFuture.get(); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); //assertTrue(bindListener.isInvoked()); // FIXME XNIO-192 //assertSame(assembledChannel, bindListener.getChannel()); assertEquals(Xnio.ANY_LOCAL_ADDRESS, assembledChannel.getLocalAddress()); // FIXME bindAddress is ignored assertEquals(bindAddress, assembledChannel.getLocalAddress()); assertEquals(socketAddress, assembledChannel.getPeerAddress()); assertEquals(9000000l, (long) assembledChannel.getOption(Options.STACK_SIZE)); final MessageConnectionMock connectionMock = getConnectedChannel(assembledChannel); assertSame(optionMap, connectionMock.getOptionMap()); assertEquals(XnioWorkerMock.LOCAL_CHANNEL_INFO, connectionMock.getInfo()); } @Test public void connectDatagramWithInvalidAddress() { final ChannelListener<ConnectedMessageChannel> channelListener = new TestChannelListener<ConnectedMessageChannel>(); final ChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); Exception expected = null; try { xnioWorker.connectDatagram(null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectDatagram(unknownSocketAddress, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); /*expected = null; try { xnioWorker.connectDatagram(null, new LocalSocketAddress("local"), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); */ // FIXME XNIO-192 bindAddress is now ignored expected = null; try { xnioWorker.connectDatagram(new LocalSocketAddress("local"), null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectDatagram(null, null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); /*expected = null; try { xnioWorker.connectDatagram(new InetSocketAddress(800), new LocalSocketAddress("local"), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); */ // FIXME XNIO-192 now bind address is ignored expected = null; try { xnioWorker.connectDatagram(new LocalSocketAddress("local"), new InetSocketAddress(800), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.connectDatagram(unknownSocketAddress, unknownSocketAddress, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); } @Test public void acceptDatagram() throws CancellationException, IOException { final TestChannelListener<ConnectedMessageChannel> channelListener = new TestChannelListener<ConnectedMessageChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final SocketAddress localAddress = new LocalSocketAddress("here"); final OptionMap optionMap = OptionMap.create(Options.STACK_SIZE, 990000l); final IoFuture<ConnectedMessageChannel> connectedDatagramFuture = xnioWorker.acceptDatagram(localAddress, channelListener, bindListener, optionMap); assertNotNull(connectedDatagramFuture); final AssembledConnectedMessageChannel assembledChannel = (AssembledConnectedMessageChannel) connectedDatagramFuture.get(); assertTrue(channelListener.isInvoked()); assertSame(assembledChannel, channelListener.getChannel()); //assertTrue(bindListener.isInvoked()); // FIXME XNIO-192 //assertSame(assembledChannel, bindListener.getChannel()); assertEquals(localAddress, assembledChannel.getPeerAddress()); assertEquals(990000l, (long) assembledChannel.getOption(Options.STACK_SIZE)); final MessageConnectionMock connectionMock = getConnectedChannel(assembledChannel); assertSame(optionMap, connectionMock.getOptionMap()); assertEquals(XnioWorkerMock.LOCAL_CHANNEL_INFO, connectionMock.getInfo()); } @Test public void acceptDatagramWithInvalidAddress() { final TestChannelListener<ConnectedMessageChannel> channelListener = new TestChannelListener<ConnectedMessageChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); Exception expected = null; try { xnioWorker.acceptDatagram(null, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.acceptDatagram(new InetSocketAddress(10), channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.acceptDatagram(unknownSocketAddress, channelListener, bindListener, OptionMap.EMPTY); } catch (IllegalArgumentException e) { expected = e; } assertNotNull(expected); } @Test public void createUdpServer() throws IOException { final InetSocketAddress address = new InetSocketAddress(0); final OptionMap optionMap = OptionMap.create(Options.MULTICAST, true, Options.SECURE, false); MulticastMessageChannel channel = xnioWorker.createUdpServer(address, optionMap); assertNotNull(channel); // check address assertEquals(address, channel.getLocalAddress()); // check optionMap assertTrue(channel instanceof MulticastMessageChannelMock); Mock channelMock = (Mock) channel; assertEquals(optionMap, channelMock.getOptionMap()); } @Test public void createUdpServerWithListener() throws IOException { final InetSocketAddress address = new InetSocketAddress(0); final TestChannelListener<MulticastMessageChannel> listener = new TestChannelListener<MulticastMessageChannel>(); final OptionMap optionMap = OptionMap.create(Options.MULTICAST, true, Options.SECURE, true); MulticastMessageChannel channel = xnioWorker.createUdpServer(address, listener, optionMap); assertNotNull(channel); // check address assertEquals(address, channel.getLocalAddress()); // check listener assertTrue(listener.isInvoked()); assertSame(channel, listener.getChannel()); // check optionMap assertTrue(channel instanceof MulticastMessageChannelMock); Mock channelMock = (Mock) channel; assertEquals(optionMap, channelMock.getOptionMap()); } @Test public void executeCommandsAndShutdownTaskPool() throws InterruptedException { final TestCommand command1 = new TestCommand(); final TestCommand command2 = new TestCommand(); final TestCommand command3 = new TestCommand(); final TestCommand command4 = new TestCommand(); final TestCommand command5 = new TestCommand(); xnioWorker.execute(command1); xnioWorker.execute(command2); xnioWorker.execute(command3); xnioWorker.shutDownTaskPool(); RejectedExecutionException expected = null; try { xnioWorker.execute(command4); } catch (RejectedExecutionException e) { expected = e; } assertNotNull(expected); command1.waitCompletion(); command2.waitCompletion(); command3.waitCompletion(); xnioWorker.shutDownTaskPoolNow(); expected = null; try { xnioWorker.execute(command5); } catch (RejectedExecutionException e) { expected = e; } assertNotNull(expected); } @Test public void shutdownTaskPoolNow() throws InterruptedException { final TestCommand command = new TestCommand(); xnioWorker.shutDownTaskPoolNow(); RejectedExecutionException expected = null; try { xnioWorker.execute(command); } catch (RejectedExecutionException e) { expected = e; } assertNotNull(expected); } @Test public void optionsSupported() { assertTrue(xnioWorker.supportsOption(Options.WORKER_TASK_CORE_THREADS)); assertTrue(xnioWorker.supportsOption(Options.WORKER_TASK_MAX_THREADS)); assertTrue(xnioWorker.supportsOption(Options.WORKER_TASK_KEEPALIVE)); assertFalse(xnioWorker.supportsOption(Options.ALLOW_BLOCKING)); assertFalse(xnioWorker.supportsOption(Options.MULTICAST)); assertFalse(xnioWorker.supportsOption(Options.BROADCAST)); assertFalse(xnioWorker.supportsOption(Options.CLOSE_ABORT)); assertFalse(xnioWorker.supportsOption(Options.RECEIVE_BUFFER)); assertFalse(xnioWorker.supportsOption(Options.REUSE_ADDRESSES)); assertFalse(xnioWorker.supportsOption(Options.SEND_BUFFER)); assertFalse(xnioWorker.supportsOption(Options.TCP_NODELAY)); assertFalse(xnioWorker.supportsOption(Options.MULTICAST_TTL)); assertFalse(xnioWorker.supportsOption(Options.IP_TRAFFIC_CLASS)); assertFalse(xnioWorker.supportsOption(Options.TCP_OOB_INLINE)); assertFalse(xnioWorker.supportsOption(Options.KEEP_ALIVE)); assertFalse(xnioWorker.supportsOption(Options.BACKLOG)); assertFalse(xnioWorker.supportsOption(Options.READ_TIMEOUT)); assertFalse(xnioWorker.supportsOption(Options.WRITE_TIMEOUT)); assertFalse(xnioWorker.supportsOption(Options.MAX_INBOUND_MESSAGE_SIZE)); assertFalse(xnioWorker.supportsOption(Options.MAX_OUTBOUND_MESSAGE_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_ENABLED)); assertFalse(xnioWorker.supportsOption(Options.SSL_CLIENT_AUTH_MODE)); assertFalse(xnioWorker.supportsOption(Options.SSL_ENABLED_CIPHER_SUITES)); assertFalse(xnioWorker.supportsOption(Options.SSL_SUPPORTED_CIPHER_SUITES)); assertFalse(xnioWorker.supportsOption(Options.SSL_ENABLED_PROTOCOLS)); assertFalse(xnioWorker.supportsOption(Options.SSL_SUPPORTED_PROTOCOLS)); assertFalse(xnioWorker.supportsOption(Options.SSL_PROVIDER)); assertFalse(xnioWorker.supportsOption(Options.SSL_PROTOCOL)); assertFalse(xnioWorker.supportsOption(Options.SSL_ENABLE_SESSION_CREATION)); assertFalse(xnioWorker.supportsOption(Options.SSL_USE_CLIENT_MODE)); assertFalse(xnioWorker.supportsOption(Options.SSL_CLIENT_SESSION_CACHE_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_CLIENT_SESSION_TIMEOUT)); assertFalse(xnioWorker.supportsOption(Options.SSL_SERVER_SESSION_CACHE_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_SERVER_SESSION_TIMEOUT)); assertFalse(xnioWorker.supportsOption(Options.SSL_JSSE_KEY_MANAGER_CLASSES)); assertFalse(xnioWorker.supportsOption(Options.SSL_JSSE_TRUST_MANAGER_CLASSES)); assertFalse(xnioWorker.supportsOption(Options.SSL_RNG_OPTIONS)); assertFalse(xnioWorker.supportsOption(Options.SSL_PACKET_BUFFER_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_APPLICATION_BUFFER_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_PACKET_BUFFER_REGION_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_APPLICATION_BUFFER_REGION_SIZE)); assertFalse(xnioWorker.supportsOption(Options.SSL_STARTTLS)); assertFalse(xnioWorker.supportsOption(Options.SSL_PEER_HOST_NAME)); assertFalse(xnioWorker.supportsOption(Options.SSL_PEER_PORT)); assertFalse(xnioWorker.supportsOption(Options.USE_DIRECT_BUFFERS)); assertFalse(xnioWorker.supportsOption(Options.SECURE)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_FORWARD_SECRECY)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_NOACTIVE)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_NOANONYMOUS)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_NODICTIONARY)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_NOPLAINTEXT)); assertFalse(xnioWorker.supportsOption(Options.SASL_POLICY_PASS_CREDENTIALS)); assertFalse(xnioWorker.supportsOption(Options.SASL_QOP)); assertFalse(xnioWorker.supportsOption(Options.SASL_STRENGTH)); assertFalse(xnioWorker.supportsOption(Options.SASL_SERVER_AUTH)); assertFalse(xnioWorker.supportsOption(Options.SASL_REUSE)); assertFalse(xnioWorker.supportsOption(Options.SASL_MECHANISMS)); assertFalse(xnioWorker.supportsOption(Options.SASL_DISALLOWED_MECHANISMS)); assertFalse(xnioWorker.supportsOption(Options.SASL_PROPERTIES)); assertFalse(xnioWorker.supportsOption(Options.FILE_ACCESS)); assertFalse(xnioWorker.supportsOption(Options.STACK_SIZE)); assertFalse(xnioWorker.supportsOption(Options.WORKER_NAME)); assertFalse(xnioWorker.supportsOption(Options.THREAD_PRIORITY)); assertFalse(xnioWorker.supportsOption(Options.THREAD_DAEMON)); assertFalse(xnioWorker.supportsOption(Options.WORKER_READ_THREADS)); assertFalse(xnioWorker.supportsOption(Options.WORKER_WRITE_THREADS)); assertFalse(xnioWorker.supportsOption(Options.WORKER_ESTABLISH_WRITING)); assertFalse(xnioWorker.supportsOption(Options.WORKER_ACCEPT_THREADS)); assertFalse(xnioWorker.supportsOption(Options.WORKER_TASK_LIMIT)); assertFalse(xnioWorker.supportsOption(Options.CORK)); assertFalse(xnioWorker.supportsOption(Options.CONNECTION_HIGH_WATER)); assertFalse(xnioWorker.supportsOption(Options.CONNECTION_LOW_WATER)); } @Test public void setAndGetOption() throws IllegalArgumentException, IOException { xnioWorker.setOption(Options.WORKER_TASK_CORE_THREADS, 3); assertEquals(3, (int) xnioWorker.setOption(Options.WORKER_TASK_CORE_THREADS, 5)); assertEquals(5, (int) xnioWorker.getOption(Options.WORKER_TASK_CORE_THREADS)); xnioWorker.setOption(Options.WORKER_TASK_MAX_THREADS, 15); assertEquals(15, (int) xnioWorker.setOption(Options.WORKER_TASK_MAX_THREADS, 8)); assertEquals(8, (int) xnioWorker.getOption(Options.WORKER_TASK_MAX_THREADS)); xnioWorker.setOption(Options.WORKER_TASK_KEEPALIVE, 500); assertEquals(500l, (int) xnioWorker.setOption(Options.WORKER_TASK_KEEPALIVE, 50)); assertEquals(50, (int) xnioWorker.getOption(Options.WORKER_TASK_KEEPALIVE)); assertNull(xnioWorker.setOption(Options.KEEP_ALIVE, true)); assertNull(xnioWorker.getOption(Options.KEEP_ALIVE)); } @Test public void optionRetrieval() throws IllegalArgumentException, IOException { final Xnio xnio = Xnio.getInstance(); final OptionMap.Builder builder = OptionMap.builder(); builder.set(Options.WORKER_NAME, "**WoRkEr**"); builder.set(Options.WORKER_TASK_LIMIT, 0x8000); builder.set(Options.WORKER_TASK_CORE_THREADS, 10); builder.set(Options.WORKER_TASK_MAX_THREADS, 20); builder.set(Options.WORKER_TASK_KEEPALIVE, 300); builder.set(Options.THREAD_DAEMON, true); xnioWorker = xnio.createWorker(builder.getMap()); assertNotNull(xnioWorker); assertEquals("**WoRkEr**", xnioWorker.getName()); assertNull(xnioWorker.getOption(Options.WORKER_NAME)); assertNull(xnioWorker.getOption(Options.WORKER_TASK_LIMIT)); assertEquals(10, (int) xnioWorker.getOption(Options.WORKER_TASK_CORE_THREADS)); assertEquals(20, (int) xnioWorker.getOption(Options.WORKER_TASK_MAX_THREADS)); assertEquals(300, (int) xnioWorker.getOption(Options.WORKER_TASK_KEEPALIVE)); } @Test public void implementationMustOverrideMethods() throws IOException { final XnioWorker.Builder builder = Xnio.getInstance().createWorkerBuilder(); builder.setTerminationTask(() -> {}); builder.setThreadGroup(Thread.currentThread().getThreadGroup()); final XnioWorker xnioWorker = new XnioWorker(builder) { @Override public void shutdown() {} @Override public List<Runnable> shutdownNow() {return null;} @Override public boolean isShutdown() {return false;} @Override public boolean isTerminated() {return false;} @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return false; } @Override public void awaitTermination() throws InterruptedException { } @Override public XnioIoThread getIoThread(final int hashCode) { return new XnioIoThreadMock(this); } @Override public int getIoThreadCount() { return 0; } @Override protected XnioIoThread chooseThread() { return new XnioIoThreadMock(this); } @Override public XnioWorkerMXBean getMXBean() { return null; } @Override protected ManagementRegistration registerServerMXBean(XnioServerMXBean metrics) { return null; } }; UnsupportedOperationException expected = null; try { xnioWorker.createStreamConnectionServer(new InetSocketAddress(1000), null, null); } catch (UnsupportedOperationException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.createStreamConnectionServer(new LocalSocketAddress("server"), null, null); } catch (UnsupportedOperationException e) { expected = e; } assertNotNull(expected); expected = null; try { xnioWorker.createUdpServer(null, null); } catch (UnsupportedOperationException e) { expected = e; } assertNotNull(expected); } private static class TestChannelListener<C extends Channel> implements ChannelListener<C> { private boolean invoked = false; private C channel; @Override public void handleEvent(C c) { invoked = true; channel = c; } public boolean isInvoked() { return invoked; } public C getChannel() { return channel; } } private static class TestCommand implements Runnable { private CountDownLatch latch = new CountDownLatch(1); @Override public void run() { latch.countDown(); } public void waitCompletion() throws InterruptedException { latch.await(); } } private static final Field connectedChannelField; private static final Field connectionField; static { try { connectedChannelField = AssembledConnectedStreamChannel.class.getDeclaredField("connection"); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (SecurityException e) { throw new RuntimeException(e); } connectedChannelField.setAccessible(true); try { connectionField = AssembledConnectedMessageChannel.class.getDeclaredField("connection"); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (SecurityException e) { throw new RuntimeException(e); } connectionField.setAccessible(true); } private StreamConnectionMock getConnectedChannel(AssembledConnectedStreamChannel assembledChannel) { try { return (StreamConnectionMock) connectedChannelField.get(assembledChannel); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } private MessageConnectionMock getConnectedChannel(AssembledConnectedMessageChannel assembledChannel) { try { return (MessageConnectionMock) connectionField.get(assembledChannel); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } }