diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java index 986bb2b701..b64abb675e 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java @@ -15,21 +15,18 @@ */ package io.netty.example.qotm; -import java.net.InetSocketAddress; -import java.util.concurrent.Executors; - -import io.netty.bootstrap.ConnectionlessBootstrap; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPipelineFactory; -import io.netty.channel.Channels; -import io.netty.channel.FixedReceiveBufferSizePredictorFactory; -import io.netty.channel.socket.DatagramChannel; -import io.netty.channel.socket.DatagramChannelFactory; -import io.netty.channel.socket.nio.NioDatagramChannelFactory; -import io.netty.handler.codec.string.StringDecoder; -import io.netty.handler.codec.string.StringEncoder; +import io.netty.buffer.ChannelBuffers; +import io.netty.channel.Channel; +import io.netty.channel.ChannelBootstrap; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.socket.DatagramPacket; +import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.channel.socket.nio.SelectorEventLoop; import io.netty.util.CharsetUtil; +import java.net.InetSocketAddress; + /** * A UDP broadcast client that asks for a quote of the moment (QOTM) to * {@link QuoteOfTheMomentServer}. @@ -44,53 +41,36 @@ public class QuoteOfTheMomentClient { this.port = port; } - public void run() { - DatagramChannelFactory f = - new NioDatagramChannelFactory(Executors.newCachedThreadPool()); + public void run() throws Exception { + ChannelBootstrap b = new ChannelBootstrap(); + try { + b.eventLoop(new SelectorEventLoop()) + .channel(new NioDatagramChannel()) + .localAddress(new InetSocketAddress(0)) + .option(ChannelOption.SO_BROADCAST, true) + .initializer(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + ch.pipeline().addLast(new QuoteOfTheMomentClientHandler()); + } + }); - ConnectionlessBootstrap b = new ConnectionlessBootstrap(f); + Channel ch = b.bind().sync().channel(); - // Configure the pipeline factory. - b.setPipelineFactory(new ChannelPipelineFactory() { - public ChannelPipeline getPipeline() throws Exception { - return Channels.pipeline( - new StringEncoder(CharsetUtil.ISO_8859_1), - new StringDecoder(CharsetUtil.ISO_8859_1), - new QuoteOfTheMomentClientHandler()); + // Broadcast the QOTM request to port 8080. + ch.write(new DatagramPacket( + ChannelBuffers.copiedBuffer("QOTM?", CharsetUtil.UTF_8), + new InetSocketAddress("255.255.255.255", port))); + + // QuoteOfTheMomentClientHandler will close the DatagramChannel when a + // response is received. If the channel is not closed within 5 seconds, + // print an error message and quit. + if (!ch.closeFuture().await(5000)) { + System.err.println("QOTM request timed out."); } - }); - - // Enable broadcast - b.setOption("broadcast", "true"); - - // Allow packets as large as up to 1024 bytes (default is 768). - // You could increase or decrease this value to avoid truncated packets - // or to improve memory footprint respectively. - // - // Please also note that a large UDP packet might be truncated or - // dropped by your router no matter how you configured this option. - // In UDP, a packet is truncated or dropped if it is larger than a - // certain size, depending on router configuration. IPv4 routers - // truncate and IPv6 routers drop a large packet. That's why it is - // safe to send small packets in UDP. - b.setOption( - "receiveBufferSizePredictorFactory", - new FixedReceiveBufferSizePredictorFactory(1024)); - - DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0)); - - // Broadcast the QOTM request to port 8080. - c.write("QOTM?", new InetSocketAddress("255.255.255.255", port)); - - // QuoteOfTheMomentClientHandler will close the DatagramChannel when a - // response is received. If the channel is not closed within 5 seconds, - // print an error message and quit. - if (!c.getCloseFuture().awaitUninterruptibly(5000)) { - System.err.println("QOTM request timed out."); - c.close().awaitUninterruptibly(); + } finally { + b.shutdown(); } - - f.releaseExternalResources(); } public static void main(String[] args) throws Exception { diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java index a655588f01..7295c98545 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java @@ -15,27 +15,30 @@ */ package io.netty.example.qotm; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ExceptionEvent; -import io.netty.channel.MessageEvent; -import io.netty.channel.SimpleChannelUpstreamHandler; +import io.netty.channel.ChannelInboundHandlerContext; +import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.channel.socket.DatagramPacket; +import io.netty.util.CharsetUtil; + +public class QuoteOfTheMomentClientHandler extends ChannelInboundMessageHandlerAdapter { -public class QuoteOfTheMomentClientHandler extends SimpleChannelUpstreamHandler { @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + public void messageReceived( + ChannelInboundHandlerContext ctx, DatagramPacket msg) throws Exception { - String msg = (String) e.getMessage(); - if (msg.startsWith("QOTM: ")) { - System.out.println("Quote of the Moment: " + msg.substring(6)); - e.channel().close(); + String response = msg.data().toString(CharsetUtil.UTF_8); + if (response.startsWith("QOTM: ")) { + System.out.println("Quote of the Moment: " + response.substring(6)); + ctx.close(); } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + public void exceptionCaught( + ChannelInboundHandlerContext ctx, Throwable cause) throws Exception { - e.cause().printStackTrace(); - e.channel().close(); + cause.printStackTrace(); + ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServer.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServer.java index fc035b8f83..57d329dbe0 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServer.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServer.java @@ -15,19 +15,14 @@ */ package io.netty.example.qotm; -import java.net.InetSocketAddress; -import java.util.concurrent.Executors; +import io.netty.channel.Channel; +import io.netty.channel.ChannelBootstrap; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.channel.socket.nio.SelectorEventLoop; -import io.netty.bootstrap.ConnectionlessBootstrap; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPipelineFactory; -import io.netty.channel.Channels; -import io.netty.channel.FixedReceiveBufferSizePredictorFactory; -import io.netty.channel.socket.DatagramChannelFactory; -import io.netty.channel.socket.nio.NioDatagramChannelFactory; -import io.netty.handler.codec.string.StringDecoder; -import io.netty.handler.codec.string.StringEncoder; -import io.netty.util.CharsetUtil; +import java.net.InetSocketAddress; /** * A UDP server that responds to the QOTM (quote of the moment) request to a @@ -43,41 +38,24 @@ public class QuoteOfTheMomentServer { this.port = port; } - public void run() { - DatagramChannelFactory f = - new NioDatagramChannelFactory(Executors.newCachedThreadPool()); + public void run() throws Exception { + ChannelBootstrap b = new ChannelBootstrap(); + try { + b.eventLoop(new SelectorEventLoop()) + .channel(new NioDatagramChannel()) + .localAddress(new InetSocketAddress(port)) + .option(ChannelOption.SO_BROADCAST, true) + .initializer(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + ch.pipeline().addLast(new QuoteOfTheMomentServerHandler()); + } + }); - ConnectionlessBootstrap b = new ConnectionlessBootstrap(f); - - // Configure the pipeline factory. - b.setPipelineFactory(new ChannelPipelineFactory() { - public ChannelPipeline getPipeline() throws Exception { - return Channels.pipeline( - new StringEncoder(CharsetUtil.ISO_8859_1), - new StringDecoder(CharsetUtil.ISO_8859_1), - new QuoteOfTheMomentServerHandler()); - } - }); - - // Enable broadcast - b.setOption("broadcast", "false"); - - // Allow packets as large as up to 1024 bytes (default is 768). - // You could increase or decrease this value to avoid truncated packets - // or to improve memory footprint respectively. - // - // Please also note that a large UDP packet might be truncated or - // dropped by your router no matter how you configured this option. - // In UDP, a packet is truncated or dropped if it is larger than a - // certain size, depending on router configuration. IPv4 routers - // truncate and IPv6 routers drop a large packet. That's why it is - // safe to send small packets in UDP. - b.setOption( - "receiveBufferSizePredictorFactory", - new FixedReceiveBufferSizePredictorFactory(1024)); - - // Bind to the port and start the service. - b.bind(new InetSocketAddress(port)); + b.bind().sync().channel().closeFuture().await(); + } finally { + b.shutdown(); + } } public static void main(String[] args) throws Exception { diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java index f87c808fd7..68ca7ccc7b 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java @@ -15,14 +15,15 @@ */ package io.netty.example.qotm; +import io.netty.buffer.ChannelBuffers; +import io.netty.channel.ChannelInboundHandlerContext; +import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.channel.socket.DatagramPacket; +import io.netty.util.CharsetUtil; + import java.util.Random; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ExceptionEvent; -import io.netty.channel.MessageEvent; -import io.netty.channel.SimpleChannelUpstreamHandler; - -public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler { +public class QuoteOfTheMomentServerHandler extends ChannelInboundMessageHandlerAdapter { private static final Random random = new Random(); @@ -43,18 +44,21 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler } @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + public void messageReceived( + ChannelInboundHandlerContext ctx, DatagramPacket msg) throws Exception { - String msg = (String) e.getMessage(); - if (msg.equals("QOTM?")) { - e.channel().write("QOTM: " + nextQuote(), e.getRemoteAddress()); + if (msg.data().toString(CharsetUtil.UTF_8).equals("QOTM?")) { + ctx.write(new DatagramPacket( + ChannelBuffers.copiedBuffer("QOTM: " + nextQuote(), CharsetUtil.UTF_8), + msg.remoteAddress())); } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + public void exceptionCaught( + ChannelInboundHandlerContext ctx, Throwable cause) throws Exception { - e.cause().printStackTrace(); + cause.printStackTrace(); // We don't close the channel because we can keep serving requests. } } diff --git a/transport/src/main/java/io/netty/channel/socket/nio/DefaultNioDatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/nio/DefaultNioDatagramChannelConfig.java index 87d0090bb5..b2a95eb1f7 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/DefaultNioDatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/DefaultNioDatagramChannelConfig.java @@ -42,29 +42,29 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig { } Object ipMulticastIf = null; + Method getOption = null; + Method setOption = null; if (socketOptionType != null) { try { ipMulticastIf = Class.forName("java.net.StandardSocketOptions", true, classLoader).getDeclaredField("IP_MULTICAST_IF").get(null); } catch (Exception e) { throw new Error("cannot locate the IP_MULTICAST_IF field", e); } + + try { + getOption = DatagramChannel.class.getDeclaredMethod("getOption", socketOptionType); + } catch (Exception e) { + throw new Error("cannot locate the getOption() method", e); + } + + try { + setOption = DatagramChannel.class.getDeclaredMethod("setOption", socketOptionType, Object.class); + } catch (Exception e) { + throw new Error("cannot locate the setOption() method", e); + } } IP_MULTICAST_IF = ipMulticastIf; - - Method getOption; - try { - getOption = DatagramChannel.class.getDeclaredMethod("getOption", socketOptionType); - } catch (Exception e) { - throw new Error("cannot locate the getOption() method", e); - } GET_OPTION = getOption; - - Method setOption; - try { - setOption = DatagramChannel.class.getDeclaredMethod("setOption", socketOptionType, Object.class); - } catch (Exception e) { - throw new Error("cannot locate the setOption() method", e); - } SET_OPTION = setOption; } diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java index 7f71645e6d..d8504eb088 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java @@ -126,7 +126,7 @@ public final class NioDatagramChannel extends AbstractNioChannel implements io.n @Override protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().bind(localAddress); + javaChannel().socket().bind(localAddress); selectionKey().interestOps(SelectionKey.OP_READ); } @@ -174,6 +174,7 @@ public final class NioDatagramChannel extends AbstractNioChannel implements io.n @Override protected int doRead(ChannelBufferHolder buf) throws Exception { DatagramChannel ch = javaChannel(); + // FIXME: Make this configurable. ByteBuffer data = ByteBuffer.allocate(1024); InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(data); if (remoteAddress == null) { diff --git a/transport/src/test/java/io/netty/bootstrap/BootstrapOrderedMapTest.java b/transport/src/test/java/io/netty/bootstrap/BootstrapOrderedMapTest.java deleted file mode 100644 index 83297e1d46..0000000000 --- a/transport/src/test/java/io/netty/bootstrap/BootstrapOrderedMapTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.bootstrap; - -import static org.junit.Assert.*; - -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import org.junit.Test; - - -/** - * A test to make sure that a bootstrap can recognize ordered maps - */ -public class BootstrapOrderedMapTest { - - @Test - public void shouldReturnTrueIfLinkedHashMap() { - assertTrue(Bootstrap.isOrderedMap(new LinkedHashMap())); - } - - @Test - public void shouldReturnTrueIfMapImplementsOrderedMap() { - assertTrue(Bootstrap.isOrderedMap(new DummyOrderedMap())); - } - - @Test - public void shouldReturnFalseIfMapHasNoDefaultConstructor() { - assertFalse(Bootstrap.isOrderedMap( - new MapWithoutDefaultConstructor( - new HashMap()))); - } - - @Test - public void shouldReturnFalseIfMapIsNotOrdered() { - assertFalse(Bootstrap.isOrderedMap(new HashMap())); - } - - @Test - public void shouldReturnTrueIfMapIsOrdered() { - assertTrue(Bootstrap.isOrderedMap(new UnknownOrderedMap())); - } - - interface OrderedMap { - // A tag interface - } - - static class DummyOrderedMap extends AbstractMap implements OrderedMap { - - private final Map map = new HashMap(); - - @Override - public Set> entrySet() { - return map.entrySet(); - } - } - - static class MapWithoutDefaultConstructor extends AbstractMap { - private final Map map; - - MapWithoutDefaultConstructor(Map map) { - this.map = map; - } - - @Override - public Set> entrySet() { - return map.entrySet(); - } - } - - static class UnknownOrderedMap extends AbstractMap { - - private final Map map = new LinkedHashMap(); - - @Override - public boolean containsKey(Object key) { - return map.containsKey(key); - } - - @Override - public int size() { - return map.size(); - } - - @Override - public V put(K key, V value) { - return map.put(key, value); - } - - @Override - public Set keySet() { - return map.keySet(); - } - - @Override - public Set> entrySet() { - return map.entrySet(); - } - } -} diff --git a/transport/src/test/java/io/netty/bootstrap/BootstrapTest.java b/transport/src/test/java/io/netty/bootstrap/BootstrapTest.java deleted file mode 100644 index a7accc23e2..0000000000 --- a/transport/src/test/java/io/netty/bootstrap/BootstrapTest.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright 2011 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.bootstrap; - -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Map.Entry; - -import io.netty.channel.ChannelDownstreamHandler; -import io.netty.channel.ChannelEvent; -import io.netty.channel.ChannelFactory; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPipelineFactory; -import io.netty.channel.ChannelUpstreamHandler; - -import org.junit.Test; - - -/** - * A bootstrap test - */ -public class BootstrapTest { - - /** - * Tests to make sure that a new bootstrap should not return null, but an IllegalStateException - */ - @Test(expected = IllegalStateException.class) - public void shouldNotReturnNullFactory() { - new Bootstrap().getFactory(); - } - - /** - * Tests to make sure that a new bootstrap cannot have it's channel factory changed - */ - @Test(expected = IllegalStateException.class) - public void shouldNotAllowInitialFactoryToChange() { - new Bootstrap(createMock(ChannelFactory.class)).setFactory(createMock(ChannelFactory.class)); - } - - /** - * Tests to make sure that a bootstrap's factory can only be set once and not reset after that - */ - @Test - public void shouldNotAllowFactoryToChangeMoreThanOnce() { - //Initialize a new bootstrap - Bootstrap b = new Bootstrap(); - //Create a mock-up ChannelFactory - ChannelFactory f = createMock(ChannelFactory.class); - //Set the bootstrap's channel factory - b.setFactory(f); - //Assert that both f and the bootstrap's factory are the same - assertSame(f, b.getFactory()); - - //Start a try block - try { - //Attempt to set the bootstrap's channel factory again - b.setFactory(createMock(ChannelFactory.class)); - //Fail if no exception is thrown - fail(); - } catch (IllegalStateException e) { - // Success. - } - } - - /** - * Tests to make sure that setFactory does not accept null as a parameter - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullFactory() { - new Bootstrap().setFactory(null); - } - - /** - * Tests to make sure that a new bootstrap's default pipeline is not null - */ - @Test - public void shouldHaveNonNullInitialPipeline() { - assertNotNull(new Bootstrap().getPipeline()); - } - - /** - * Tests to make sure a bootstrap's pipeline cannot be set to null - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullPipeline() { - new Bootstrap().setPipeline(null); - } - - /** - * Tests to make sure a bootstrap cannot have it's pipeline (map) set to null - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullPipelineMap() { - new Bootstrap().setPipelineAsMap(null); - } - - /** - * Tests to make sure a bootstrap's initial pipeline factory is not null - */ - @Test - public void shouldHaveNonNullInitialPipelineFactory() { - assertNotNull(new Bootstrap().getPipelineFactory()); - } - - /** - * Tests to make sure that a bootstrap's pipeline factory changes if a new pipeline is set - */ - @Test - public void shouldUpdatePipelineFactoryIfPipelineIsSet() { - //Make a new bootstrap - Bootstrap b = new Bootstrap(); - //Get the initial pipeline factory - ChannelPipelineFactory oldPipelineFactory = b.getPipelineFactory(); - //Set a new pipeline - b.setPipeline(createMock(ChannelPipeline.class)); - //Assert that the new pipeline factory is not the same as the initial one - assertNotSame(oldPipelineFactory, b.getPipelineFactory()); - } - - /** - * Tests to make sure a bootstrap's pipeline is not returned when a pipeline factory is explicitly set - */ - @Test(expected = IllegalStateException.class) - public void shouldNotReturnPipelineWhenPipelineFactoryIsSetByUser() { - Bootstrap b = new Bootstrap(); - b.setPipelineFactory(createMock(ChannelPipelineFactory.class)); - b.getPipeline(); - } - - /** - * Tests to make sure a bootstrap's pipeline map is not returned when a pipeline factory is explicitly set - */ - @Test(expected = IllegalStateException.class) - public void shouldNotReturnPipelineMapWhenPipelineFactoryIsSetByUser() { - Bootstrap b = new Bootstrap(); - b.setPipelineFactory(createMock(ChannelPipelineFactory.class)); - b.getPipelineAsMap(); - } - - /** - * Tests to make sure a bootstrap's pipeline factory cannot be set to null - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullPipelineFactory() { - new Bootstrap().setPipelineFactory(null); - } - - /** - * Tests to make sure a new bootstrap's pipeline map is empty - */ - @Test - public void shouldHaveInitialEmptyPipelineMap() { - assertTrue(new Bootstrap().getPipelineAsMap().isEmpty()); - } - - /** - * Tests to make sure that a buffer's pipeline map is ordered - */ - @Test - public void shouldReturnOrderedPipelineMap() { - Bootstrap b = new Bootstrap(); - ChannelPipeline p = b.getPipeline(); - p.addLast("a", new DummyHandler()); - p.addLast("b", new DummyHandler()); - p.addLast("c", new DummyHandler()); - p.addLast("d", new DummyHandler()); - - Iterator> m = - b.getPipelineAsMap().entrySet().iterator(); - Entry e; - e = m.next(); - assertEquals("a", e.getKey()); - assertSame(p.get("a"), e.getValue()); - e = m.next(); - assertEquals("b", e.getKey()); - assertSame(p.get("b"), e.getValue()); - e = m.next(); - assertEquals("c", e.getKey()); - assertSame(p.get("c"), e.getValue()); - e = m.next(); - assertEquals("d", e.getKey()); - assertSame(p.get("d"), e.getValue()); - - assertFalse(m.hasNext()); - } - - /** - * Tests to make sure that a buffer's pipeline map cannot be set to an unordered map - */ - @Test(expected = IllegalArgumentException.class) - public void shouldNotAllowUnorderedPipelineMap() { - Map m = new HashMap(); - m.put("a", new DummyHandler()); - m.put("b", new DummyHandler()); - m.put("c", new DummyHandler()); - m.put("d", new DummyHandler()); - - Bootstrap b = new Bootstrap(); - b.setPipelineAsMap(m); - } - - /** - * Tests to make sure a buffer's pipeline is ordered when it is set from a map - */ - @Test - public void shouldHaveOrderedPipelineWhenSetFromMap() { - Map m = new LinkedHashMap(); - m.put("a", new DummyHandler()); - m.put("b", new DummyHandler()); - m.put("c", new DummyHandler()); - m.put("d", new DummyHandler()); - - Bootstrap b = new Bootstrap(); - b.setPipelineAsMap(m); - - ChannelPipeline p = b.getPipeline(); - - assertSame(p.first(), m.get("a")); - assertEquals("a", p.context(p.first()).name()); - p.removeFirst(); - assertSame(p.first(), m.get("b")); - assertEquals("b", p.context(p.first()).name()); - p.removeFirst(); - assertSame(p.first(), m.get("c")); - assertEquals("c", p.context(p.first()).name()); - p.removeFirst(); - assertSame(p.first(), m.get("d")); - assertEquals("d", p.context(p.first()).name()); - p.removeFirst(); - - try { - p.removeFirst(); - fail(); - } catch (NoSuchElementException e) { - // Success. - } - } - - /** - * Tests to make sure that a new bootstrap should not have any options set - */ - @Test - public void shouldHaveInitialEmptyOptionMap() { - assertTrue(new Bootstrap().getOptions().isEmpty()); - } - - /** - * Tests to make sure that a bootstrap's option map updates in real time - */ - @Test - public void shouldUpdateOptionMapAsRequested1() { - Bootstrap b = new Bootstrap(); - b.setOption("s", "x"); - b.setOption("b", true); - b.setOption("i", 42); - - Map o = b.getOptions(); - assertEquals(3, o.size()); - assertEquals("x", o.get("s")); - assertEquals(true, o.get("b")); - assertEquals(42, o.get("i")); - } - - /** - * Tests to make sure that a bootstrap's option map updates in real time - */ - @Test - public void shouldUpdateOptionMapAsRequested2() { - Bootstrap b = new Bootstrap(); - Map o1 = new HashMap(); - o1.put("s", "x"); - o1.put("b", true); - o1.put("i", 42); - b.setOptions(o1); - - Map o2 = b.getOptions(); - assertEquals(3, o2.size()); - assertEquals("x", o2.get("s")); - assertEquals(true, o2.get("b")); - assertEquals(42, o2.get("i")); - - assertNotSame(o1, o2); - assertEquals(o1, o2); - } - - /** - * Tests to make sure that an option is removed from a buffer's options when the option is set to null - */ - @Test - public void shouldRemoveOptionIfValueIsNull() { - Bootstrap b = new Bootstrap(); - - b.setOption("s", "x"); - assertEquals("x", b.getOption("s")); - - b.setOption("s", null); - assertNull(b.getOption("s")); - assertTrue(b.getOptions().isEmpty()); - } - - /** - * Tests to make sure that a bootstrap can't accept null as a parameter of getOption(key) - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullOptionKeyOnGet() { - new Bootstrap().getOption(null); - } - - /** - * Tests to make sure a bootstrap can't accept a null key when using setOption(key, value) - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullOptionKeyOnSet() { - new Bootstrap().setOption(null, "x"); - } - - /** - * Tests to make sure that a boostrap can't accept a null option map - */ - @Test(expected = NullPointerException.class) - public void shouldNotAllowNullOptionMap() { - new Bootstrap().setOptions(null); - } - - private class DummyHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler { - - public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) - throws Exception { - ctx.sendUpstream(e); - } - - public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) - throws Exception { - ctx.sendDownstream(e); - } - } - -}