0c1f69836df36cbc14e993b3d0e5c50f84c57f7e
[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.DefaultPromise;
23 import io.netty.util.concurrent.EventExecutor;
24 import io.netty.util.concurrent.Future;
25 import io.netty.util.concurrent.GlobalEventExecutor;
26 import java.net.InetSocketAddress;
27 import java.nio.channels.Channel;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.concurrent.ExecutionException;
31 import org.junit.After;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.mockito.Mock;
36 import org.mockito.Mockito;
37 import org.mockito.MockitoAnnotations;
38 import org.opendaylight.protocol.concepts.KeyMapping;
39 import org.opendaylight.protocol.pcep.PCEPCapability;
40 import org.opendaylight.protocol.pcep.PCEPSession;
41 import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
42 import org.opendaylight.protocol.pcep.PCEPSessionNegotiatorFactory;
43 import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
44 import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl.ChannelPipelineInitializer;
45 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
46 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
47
48 public class PCEPDispatcherImplTest {
49
50     private static final int PORT = 4189;
51     private static final InetSocketAddress CLIENT1_ADDRESS = new InetSocketAddress("127.0.0.10", PORT);
52     private static final InetSocketAddress CLIENT2_ADDRESS = new InetSocketAddress("127.0.0.11", PORT);
53     private static final short DEAD_TIMER = 120;
54     private static final short KEEP_ALIVE = 30;
55     private static final int RETRY_TIMER = 0;
56     private static final int CONNECT_TIMEOUT = 500;
57
58     private PCEPDispatcherImpl dispatcher;
59     private PCEPDispatcherImpl disp2Spy;
60
61     @Mock private Channel mockChannel;
62
63     private PCCMock pccMock;
64
65     @Before
66     public void setUp() {
67         MockitoAnnotations.initMocks(this);
68         final List<PCEPCapability> capList = new ArrayList<>();
69         final PCEPSessionProposalFactory sessionProposal = new BasePCEPSessionProposalFactory(DEAD_TIMER, KEEP_ALIVE, capList);
70         final EventLoopGroup eventLoopGroup;
71         if (Epoll.isAvailable()) {
72             eventLoopGroup = new EpollEventLoopGroup();
73         } else {
74             eventLoopGroup = new NioEventLoopGroup();
75         }
76         final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
77                 .getMessageHandlerRegistry();
78         this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
79                 eventLoopGroup, eventLoopGroup);
80
81         Mockito.doReturn("mockChannel").when(this.mockChannel).toString();
82         final PCEPDispatcherImpl dispatcher2 = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0), eventLoopGroup, eventLoopGroup);
83         this.disp2Spy = Mockito.spy(dispatcher2);
84
85         this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
86                 new PCEPHandlerFactory(msgReg), new DefaultPromise<PCEPSessionImpl>(
87                         GlobalEventExecutor.INSTANCE));
88     }
89
90     @Test
91     public void testCreateClientServer() throws InterruptedException, ExecutionException {
92         final ChannelFuture futureChannel = this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
93                 () -> new SimpleSessionListener(), null);
94         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT1_ADDRESS,
95                 RETRY_TIMER, CONNECT_TIMEOUT,
96                 () -> new SimpleSessionListener()).get();
97
98         final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT2_ADDRESS,
99                 RETRY_TIMER, CONNECT_TIMEOUT,
100                 () -> new SimpleSessionListener()).get();
101
102         Assert.assertTrue(futureChannel.channel().isActive());
103         Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
104         Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
105         Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
106
107         Assert.assertEquals(CLIENT2_ADDRESS.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
108         Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
109         Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
110
111         session1.close();
112         session2.close();
113         Assert.assertTrue(futureChannel.channel().isActive());
114     }
115
116     @Test
117     public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
118         this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
119                 () -> new SimpleSessionListener(), null);
120         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT1_ADDRESS,
121                 RETRY_TIMER, CONNECT_TIMEOUT,
122                 () -> new SimpleSessionListener()).get();
123
124         try {
125             this.pccMock.createClient(CLIENT1_ADDRESS, RETRY_TIMER, CONNECT_TIMEOUT,
126                     () -> new SimpleSessionListener()).get();
127             Assert.fail();
128         } catch (final ExecutionException e) {
129             Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
130         } finally {
131             session1.close();
132         }
133     }
134
135     @Test
136     public void testReconectClient() throws InterruptedException, ExecutionException {
137         this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
138                 () -> new SimpleSessionListener(), null);
139         final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT1_ADDRESS,
140                 RETRY_TIMER, CONNECT_TIMEOUT,
141                 () -> new SimpleSessionListener()).get();
142
143         Assert.assertEquals(CLIENT1_ADDRESS.getAddress(), session1.getRemoteAddress());
144         Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
145         Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
146         session1.close();
147
148         final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT1_ADDRESS,
149                 RETRY_TIMER, CONNECT_TIMEOUT,
150                 () -> new SimpleSessionListener()).get();
151
152         Assert.assertEquals(CLIENT1_ADDRESS.getAddress(), session1.getRemoteAddress());
153         Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
154         Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
155
156         session2.close();
157     }
158
159     @Test
160     public void testCustomizeBootstrap() {
161         final KeyMapping keys = KeyMapping.getKeyMapping(CLIENT1_ADDRESS.getAddress(), new String("CLIENT1_ADDRESS"));
162         keys.put(CLIENT2_ADDRESS.getAddress(), new String("CLIENT2_ADDRESS").getBytes() );
163
164         final ChannelFuture futureChannel = this.disp2Spy.createServer(new InetSocketAddress("0.0.0.0", PORT),
165                 () -> new SimpleSessionListener(), null);
166         Mockito.verify(this.disp2Spy).createServerBootstrap(Mockito.any(PCEPDispatcherImpl.ChannelPipelineInitializer.class));
167     }
168
169     @After
170     public void tearDown() {
171         this.dispatcher.close();
172         this.disp2Spy.close();
173     }
174
175     private static class PCCMock {
176
177         private final PCEPSessionNegotiatorFactory negotiatorFactory;
178         private final PCEPHandlerFactory factory;
179         private final EventExecutor executor;
180         private final EventLoopGroup workerGroup;
181         private final EventLoopGroup bossGroup;
182
183         public PCCMock(final PCEPSessionNegotiatorFactory negotiatorFactory, final PCEPHandlerFactory factory,
184                 final DefaultPromise<PCEPSessionImpl> defaultPromise) {
185             this.bossGroup = Preconditions.checkNotNull(new NioEventLoopGroup());
186             this.workerGroup = Preconditions.checkNotNull(new NioEventLoopGroup());
187             this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
188             this.factory = Preconditions.checkNotNull(factory);
189             this.executor = Preconditions.checkNotNull(GlobalEventExecutor.INSTANCE);
190         }
191
192         public Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
193                 final int connectTimeout, final PCEPSessionListenerFactory listenerFactory) {
194             return createClient(address, retryTimer, connectTimeout, (ChannelPipelineInitializer) (ch, promise) -> {
195                 ch.pipeline().addLast(PCCMock.this.factory.getDecoders());
196                 ch.pipeline().addLast("negotiator", PCCMock.this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch, promise, null));
197                 ch.pipeline().addLast(PCCMock.this.factory.getEncoders());
198             });
199         }
200
201         Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer, final int connectTimeout,
202                 final PCEPDispatcherImpl.ChannelPipelineInitializer initializer) {
203             final Bootstrap b = new Bootstrap();
204             final PCEPProtocolSessionPromise p = new PCEPProtocolSessionPromise(this.executor, address, retryTimer, connectTimeout, b);
205             (b.option(ChannelOption.SO_KEEPALIVE, Boolean.valueOf(true))).handler(new ChannelInitializer<SocketChannel>() {
206                 @Override
207                 protected void initChannel(final SocketChannel ch) {
208                     initializer.initializeChannel(ch, p);
209                 }
210             });
211
212             setWorkerGroup(b);
213             setChannelFactory(b);
214             p.connect();
215             return p;
216         }
217
218         private void setChannelFactory(final Bootstrap b) {
219             try {
220                 b.channel(NioSocketChannel.class);
221             } catch (final IllegalStateException ignored) {
222             }
223
224         }
225
226         private void setWorkerGroup(final Bootstrap b) {
227             if (b.group() == null) {
228                 b.group(this.workerGroup);
229             }
230         }
231     }
232
233 }