BUG-6647 Increase code coverage and clean up II
[bgpcep.git] / pcep / impl / src / test / java / org / opendaylight / protocol / pcep / impl / PCEPDispatcherImplTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.protocol.pcep.impl;
10
11 import com.google.common.base.Preconditions;
12 import io.netty.bootstrap.Bootstrap;
13 import io.netty.channel.ChannelFuture;
14 import io.netty.channel.ChannelInitializer;
15 import io.netty.channel.ChannelOption;
16 import io.netty.channel.EventLoopGroup;
17 import io.netty.channel.epoll.Epoll;
18 import io.netty.channel.epoll.EpollEventLoopGroup;
19 import io.netty.channel.nio.NioEventLoopGroup;
20 import io.netty.channel.socket.SocketChannel;
21 import io.netty.channel.socket.nio.NioSocketChannel;
22 import io.netty.util.concurrent.EventExecutor;
23 import io.netty.util.concurrent.Future;
24 import io.netty.util.concurrent.GlobalEventExecutor;
25 import java.net.InetSocketAddress;
26 import java.nio.channels.Channel;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.concurrent.ExecutionException;
30 import org.junit.After;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.mockito.Mock;
35 import org.mockito.Mockito;
36 import org.mockito.MockitoAnnotations;
37 import org.opendaylight.protocol.concepts.KeyMapping;
38 import org.opendaylight.protocol.pcep.PCEPCapability;
39 import org.opendaylight.protocol.pcep.PCEPSession;
40 import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
41 import org.opendaylight.protocol.pcep.PCEPSessionNegotiatorFactory;
42 import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
43 import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl.ChannelPipelineInitializer;
44 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
45 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
46 import org.opendaylight.protocol.util.InetSocketAddressUtil;
47
48 public class PCEPDispatcherImplTest {
49     private static final short DEAD_TIMER = 120;
50     private static final short KEEP_ALIVE = 30;
51     private static final int RETRY_TIMER = 0;
52     private static final int CONNECT_TIMEOUT = 500;
53
54     private PCEPDispatcherImpl dispatcher;
55     private PCEPDispatcherImpl disp2Spy;
56
57     @Mock private Channel mockChannel;
58
59     private PCCMock pccMock;
60
61     @Before
62     public void setUp() {
63         MockitoAnnotations.initMocks(this);
64         final List<PCEPCapability> capList = new ArrayList<>();
65         final PCEPSessionProposalFactory sessionProposal = new BasePCEPSessionProposalFactory(DEAD_TIMER, KEEP_ALIVE, capList);
66         final EventLoopGroup eventLoopGroup;
67         if (Epoll.isAvailable()) {
68             eventLoopGroup = new EpollEventLoopGroup();
69         } else {
70             eventLoopGroup = new NioEventLoopGroup();
71         }
72         final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
73                 .getMessageHandlerRegistry();
74         this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
75                 eventLoopGroup, eventLoopGroup);
76
77         Mockito.doReturn("mockChannel").when(this.mockChannel).toString();
78         final PCEPDispatcherImpl dispatcher2 = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0), eventLoopGroup, eventLoopGroup);
79         this.disp2Spy = Mockito.spy(dispatcher2);
80
81         this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
82                 new PCEPHandlerFactory(msgReg));
83     }
84
85     @Test
86     public void testCreateClientServer() throws InterruptedException, ExecutionException {
87         final int port = InetSocketAddressUtil.getRandomPort();
88         final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
89         final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
90         final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
91         final ChannelFuture futureChannel = this.dispatcher.createServer(serverAddr,
92                 () -> new SimpleSessionListener(), null);
93         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr1,
94                 RETRY_TIMER, CONNECT_TIMEOUT,
95                 () -> new SimpleSessionListener()).get();
96
97         final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr2,
98                 RETRY_TIMER, CONNECT_TIMEOUT,
99                 () -> new SimpleSessionListener()).get();
100
101         Assert.assertTrue(futureChannel.channel().isActive());
102         Assert.assertEquals(clientAddr1.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
103         Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
104         Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
105
106         Assert.assertEquals(clientAddr2.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
107         Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
108         Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
109
110         session1.close();
111         session2.close();
112         Assert.assertTrue(futureChannel.channel().isActive());
113     }
114
115     @Test
116     public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
117         final int port = InetSocketAddressUtil.getRandomPort();
118         final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
119         final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
120         this.dispatcher.createServer(serverAddr,
121                 () -> new SimpleSessionListener(), null);
122         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
123                 RETRY_TIMER, CONNECT_TIMEOUT,
124                 () -> new SimpleSessionListener()).get();
125
126         try {
127             this.pccMock.createClient(clientAddr,
128                     RETRY_TIMER, CONNECT_TIMEOUT,
129                     () -> new SimpleSessionListener()).get();
130             Assert.fail();
131         } catch (final ExecutionException e) {
132             Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
133         } finally {
134             session1.close();
135         }
136     }
137
138     @Test
139     public void testReconectClient() throws InterruptedException, ExecutionException {
140         final int port = InetSocketAddressUtil.getRandomPort();
141         final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
142         this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", port),
143                 () -> new SimpleSessionListener(), null);
144         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
145                 RETRY_TIMER, CONNECT_TIMEOUT,
146                 () -> new SimpleSessionListener()).get();
147
148         Assert.assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
149         Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
150         Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
151         session1.close();
152
153         final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
154                 RETRY_TIMER, CONNECT_TIMEOUT,
155                 () -> new SimpleSessionListener()).get();
156
157         Assert.assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
158         Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
159         Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
160
161         session2.close();
162     }
163
164     @Test
165     public void testCustomizeBootstrap() {
166         final int port = InetSocketAddressUtil.getRandomPort();
167         final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
168         final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
169         final KeyMapping keys = KeyMapping.getKeyMapping(clientAddr1.getAddress(), new String("CLIENT1_ADDRESS"));
170         keys.put(clientAddr2.getAddress(), new String("CLIENT2_ADDRESS").getBytes() );
171
172         final ChannelFuture futureChannel = this.disp2Spy.createServer(new InetSocketAddress("0.0.0.0", port),
173                 () -> new SimpleSessionListener(), null);
174         Mockito.verify(this.disp2Spy).createServerBootstrap(Mockito.any(PCEPDispatcherImpl.ChannelPipelineInitializer.class));
175     }
176
177     @After
178     public void tearDown() {
179         this.dispatcher.close();
180         this.disp2Spy.close();
181     }
182
183     private static class PCCMock {
184
185         private final PCEPSessionNegotiatorFactory negotiatorFactory;
186         private final PCEPHandlerFactory factory;
187         private final EventExecutor executor;
188         private final EventLoopGroup workerGroup;
189
190         public PCCMock(final PCEPSessionNegotiatorFactory negotiatorFactory, final PCEPHandlerFactory factory) {
191             this.workerGroup = Preconditions.checkNotNull(new NioEventLoopGroup());
192             this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
193             this.factory = Preconditions.checkNotNull(factory);
194             this.executor = Preconditions.checkNotNull(GlobalEventExecutor.INSTANCE);
195         }
196
197         public Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
198                 final int connectTimeout, final PCEPSessionListenerFactory listenerFactory) {
199             return createClient(address, retryTimer, connectTimeout, (ChannelPipelineInitializer) (ch, promise) -> {
200                 ch.pipeline().addLast(PCCMock.this.factory.getDecoders());
201                 ch.pipeline().addLast("negotiator", PCCMock.this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch, promise, null));
202                 ch.pipeline().addLast(PCCMock.this.factory.getEncoders());
203             });
204         }
205
206         Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer, final int connectTimeout,
207                 final PCEPDispatcherImpl.ChannelPipelineInitializer initializer) {
208             final Bootstrap b = new Bootstrap();
209             final PCEPProtocolSessionPromise p = new PCEPProtocolSessionPromise(this.executor, address, retryTimer, connectTimeout, b);
210             (b.option(ChannelOption.SO_KEEPALIVE, Boolean.valueOf(true))).handler(new ChannelInitializer<SocketChannel>() {
211                 @Override
212                 protected void initChannel(final SocketChannel ch) {
213                     initializer.initializeChannel(ch, p);
214                 }
215             });
216
217             setWorkerGroup(b);
218             setChannelFactory(b);
219             p.connect();
220             return p;
221         }
222
223         private void setChannelFactory(final Bootstrap b) {
224             try {
225                 b.channel(NioSocketChannel.class);
226             } catch (final IllegalStateException ignored) {
227             }
228
229         }
230
231         private void setWorkerGroup(final Bootstrap b) {
232             if (b.group() == null) {
233                 b.group(this.workerGroup);
234             }
235         }
236     }
237
238 }