Replace Preconditions.CheckNotNull per RequireNonNull
[bgpcep.git] / pcep / impl / src / test / java / org / opendaylight / protocol / pcep / impl / PCEPDispatcherImplTest.java
old mode 100644 (file)
new mode 100755 (executable)
index f513a2a..2be37f0
 
 package org.opendaylight.protocol.pcep.impl;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
+
+import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
 import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollEventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
-import io.netty.util.concurrent.DefaultPromise;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import io.netty.util.concurrent.Promise;
 import java.net.InetSocketAddress;
+import java.nio.channels.Channel;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.protocol.framework.AbstractDispatcher;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.opendaylight.protocol.framework.ProtocolSession;
-import org.opendaylight.protocol.framework.ReconnectStrategy;
-import org.opendaylight.protocol.framework.SessionListener;
-import org.opendaylight.protocol.framework.SessionListenerFactory;
-import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
-import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.concepts.KeyMapping;
+import org.opendaylight.protocol.pcep.PCEPCapability;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionNegotiatorFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
+import org.opendaylight.protocol.util.InetSocketAddressUtil;
 
 public class PCEPDispatcherImplTest {
-
-    private static final int PORT = 4189;
-    private static final InetSocketAddress CLIENT1_ADDRESS = new InetSocketAddress("127.0.0.10", PORT);
-    private static final InetSocketAddress CLIENT2_ADDRESS = new InetSocketAddress("127.0.0.11", PORT);
     private static final short DEAD_TIMER = 120;
     private static final short KEEP_ALIVE = 30;
+    private static final int RETRY_TIMER = 0;
+    private static final int CONNECT_TIMEOUT = 500;
 
     private PCEPDispatcherImpl dispatcher;
+    private PCEPDispatcherImpl disp2Spy;
+
+    @Mock
+    private Channel mockChannel;
 
-    private PCCMock<Message, PCEPSessionImpl, PCEPSessionListener> pccMock;
+    private PCCMock pccMock;
 
     @Before
     public void setUp() {
-        final Open open = new OpenBuilder().setSessionId((short) 0).setDeadTimer(DEAD_TIMER).setKeepalive(KEEP_ALIVE)
-                .build();
-        final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = new DefaultPCEPSessionNegotiatorFactory(
-                open, 0);
-        final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
+        MockitoAnnotations.initMocks(this);
+        final List<PCEPCapability> capList = new ArrayList<>();
+        final PCEPSessionProposalFactory sessionProposal = new BasePCEPSessionProposalFactory(DEAD_TIMER, KEEP_ALIVE,
+            capList);
+        final EventLoopGroup eventLoopGroup;
+        if (Epoll.isAvailable()) {
+            eventLoopGroup = new EpollEventLoopGroup();
+        } else {
+            eventLoopGroup = new NioEventLoopGroup();
+        }
         final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
-                .getMessageHandlerRegistry();
-        this.dispatcher = new PCEPDispatcherImpl(msgReg, snf, eventLoopGroup, eventLoopGroup);
-        this.pccMock = new PCCMock<>(snf, new PCEPHandlerFactory(msgReg), new DefaultPromise<PCEPSessionImpl>(
-                GlobalEventExecutor.INSTANCE));
+            .getMessageHandlerRegistry();
+        this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
+            eventLoopGroup, eventLoopGroup);
+
+        Mockito.doReturn("mockChannel").when(this.mockChannel).toString();
+        final PCEPDispatcherImpl dispatcher2 = new PCEPDispatcherImpl(msgReg,
+            new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
+            eventLoopGroup, eventLoopGroup);
+        this.disp2Spy = Mockito.spy(dispatcher2);
+
+        this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
+            new PCEPHandlerFactory(msgReg));
     }
 
     @Test
     public void testCreateClientServer() throws InterruptedException, ExecutionException {
-        final ChannelFuture futureChannel = this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
-                new SessionListenerFactory<PCEPSessionListener>() {
-                    @Override
-                    public PCEPSessionListener getSessionListener() {
-                        return new SimpleSessionListener();
-                    }
-                });
-        final PCEPSessionImpl session1 = pccMock.createClient(CLIENT1_ADDRESS,
-                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
-                new SessionListenerFactory<PCEPSessionListener>() {
-                    @Override
-                    public PCEPSessionListener getSessionListener() {
-                        return new SimpleSessionListener();
-                    }
-                }).get();
-
-        final PCEPSessionImpl session2 = pccMock.createClient(CLIENT2_ADDRESS,
-                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
-                new SessionListenerFactory<PCEPSessionListener>() {
-                    @Override
-                    public PCEPSessionListener getSessionListener() {
-                        return new SimpleSessionListener();
-                    }
-                }).get();
+        final int port = InetSocketAddressUtil.getRandomPort();
+        final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
+        final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        final ChannelFuture futureChannel = this.dispatcher.createServer(serverAddr,
+            SimpleSessionListener::new, null);
+        waitFutureSuccess(futureChannel);
+        final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr1,
+            RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
+
+        final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr2,
+            RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
 
         Assert.assertTrue(futureChannel.channel().isActive());
-        Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
-        Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
-        Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
+        assertEquals(clientAddr1.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
+        assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
+        assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
 
-        Assert.assertEquals(CLIENT2_ADDRESS.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
-        Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
-        Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
+        assertEquals(clientAddr2.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
+        assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
+        assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
 
         session1.close();
         session2.close();
         Assert.assertTrue(futureChannel.channel().isActive());
+    }
+
+    @Test
+    public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
+        final int port = InetSocketAddressUtil.getRandomPort();
+        final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
+        final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        waitFutureSuccess(this.dispatcher.createServer(serverAddr, SimpleSessionListener::new, null));
+        final Future<PCEPSession> futureClient = this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
+            SimpleSessionListener::new);
+        waitFutureSuccess(futureClient);
+        final PCEPSessionImpl session1 = (PCEPSessionImpl) futureClient.get();
+
+        try {
+            this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
+                SimpleSessionListener::new).get();
+            Assert.fail();
+        } catch (final ExecutionException e) {
+            Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
+        } finally {
+            session1.close();
+        }
+    }
 
-        futureChannel.channel().close();
+    @Test
+    public void testReconectClient() throws InterruptedException, ExecutionException {
+        final int port = InetSocketAddressUtil.getRandomPort();
+        final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        waitFutureSuccess(this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", port),
+            SimpleSessionListener::new, null));
+        final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
+            RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
+
+        assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
+        assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
+        assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
+        waitFutureSuccess(session1.closeChannel());
+
+        final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
+            RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
+
+        assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
+        assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
+        assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
+
+        session2.close();
+    }
+
+    @Test
+    public void testCustomizeBootstrap() {
+        final int port = InetSocketAddressUtil.getRandomPort();
+        final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
+        final KeyMapping keys = KeyMapping.getKeyMapping(clientAddr1.getAddress(), "CLIENT1_ADDRESS");
+        keys.put(clientAddr2.getAddress(), "CLIENT2_ADDRESS".getBytes());
+
+        final ChannelFuture futureChannel = this.disp2Spy.createServer(new InetSocketAddress("0.0.0.0", port),
+            SimpleSessionListener::new, null);
+        waitFutureSuccess(futureChannel);
+        Mockito.verify(this.disp2Spy).createServerBootstrap(any(PCEPDispatcherImpl.ChannelPipelineInitializer.class));
     }
 
     @After
     public void tearDown() {
         this.dispatcher.close();
+        this.disp2Spy.close();
     }
 
-    private static class PCCMock<M, S extends ProtocolSession<M>, L extends SessionListener<M, ?, ?>> extends
-            AbstractDispatcher<S, L> {
-
-        private final SessionNegotiatorFactory<M, S, L> negotiatorFactory;
+    private static class PCCMock {
+        private final PCEPSessionNegotiatorFactory negotiatorFactory;
         private final PCEPHandlerFactory factory;
+        private final EventExecutor executor;
+        private final EventLoopGroup workerGroup;
+
+        PCCMock(final PCEPSessionNegotiatorFactory<?> negotiatorFactory, final PCEPHandlerFactory factory) {
+            this.workerGroup = requireNonNull(new NioEventLoopGroup());
+            this.negotiatorFactory = requireNonNull(negotiatorFactory);
+            this.factory = requireNonNull(factory);
+            this.executor = requireNonNull(GlobalEventExecutor.INSTANCE);
+        }
 
-        public PCCMock(final SessionNegotiatorFactory<M, S, L> negotiatorFactory, final PCEPHandlerFactory factory,
-                final DefaultPromise<PCEPSessionImpl> defaultPromise) {
-            super(GlobalEventExecutor.INSTANCE, new NioEventLoopGroup(), new NioEventLoopGroup());
-            this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
-            this.factory = Preconditions.checkNotNull(factory);
+        Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
+            final int connectTimeout, final PCEPSessionListenerFactory listenerFactory) {
+            return createClient(address, retryTimer, connectTimeout, (ch, promise) -> {
+                ch.pipeline().addLast(this.factory.getDecoders());
+                ch.pipeline().addLast("negotiator", this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch,
+                    promise, null));
+                ch.pipeline().addLast(this.factory.getEncoders());
+            });
         }
 
-        public Future<S> createClient(final InetSocketAddress address, final ReconnectStrategy strategy,
-                final SessionListenerFactory<L> listenerFactory) {
-            return super.createClient(address, strategy, new PipelineInitializer<S>() {
+        Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
+            final int connectTimeout, final PCEPDispatcherImpl.ChannelPipelineInitializer initializer) {
+            final Bootstrap b = new Bootstrap();
+            final PCEPProtocolSessionPromise p = new PCEPProtocolSessionPromise<>(this.executor, address, retryTimer,
+                connectTimeout, b);
+            b.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE).handler(new ChannelInitializer<SocketChannel>() {
                 @Override
-                public void initializeChannel(final SocketChannel ch, final Promise<S> promise) {
-                    ch.pipeline().addLast(PCCMock.this.factory.getDecoders());
-                    ch.pipeline().addLast("negotiator",
-                            PCCMock.this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch, promise));
-                    ch.pipeline().addLast(PCCMock.this.factory.getEncoders());
+                protected void initChannel(final SocketChannel ch) {
+                    initializer.initializeChannel(ch, p);
                 }
             });
+
+            setWorkerGroup(b);
+            setChannelFactory(b);
+            p.connect();
+            return p;
+        }
+
+        private static void setChannelFactory(final Bootstrap b) {
+            try {
+                b.channel(NioSocketChannel.class);
+            } catch (final IllegalStateException ignored) {
+            }
+        }
+
+        private void setWorkerGroup(final Bootstrap b) {
+            if (b.group() == null) {
+                b.group(this.workerGroup);
+            }
         }
     }
 
-}
+}
\ No newline at end of file