2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.protocol.pcep.impl;
11 import static java.util.Objects.requireNonNull;
12 import static org.junit.Assert.assertEquals;
13 import static org.mockito.Matchers.any;
14 import static org.mockito.Mockito.doReturn;
15 import static org.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
17 import io.netty.bootstrap.Bootstrap;
18 import io.netty.channel.ChannelFuture;
19 import io.netty.channel.ChannelInitializer;
20 import io.netty.channel.ChannelOption;
21 import io.netty.channel.EventLoopGroup;
22 import io.netty.channel.epoll.Epoll;
23 import io.netty.channel.epoll.EpollEventLoopGroup;
24 import io.netty.channel.nio.NioEventLoopGroup;
25 import io.netty.channel.socket.SocketChannel;
26 import io.netty.channel.socket.nio.NioSocketChannel;
27 import io.netty.util.concurrent.EventExecutor;
28 import io.netty.util.concurrent.Future;
29 import io.netty.util.concurrent.GlobalEventExecutor;
30 import java.net.InetSocketAddress;
31 import java.nio.channels.Channel;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.concurrent.ExecutionException;
35 import org.junit.After;
36 import org.junit.Assert;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.mockito.Mock;
40 import org.mockito.Mockito;
41 import org.mockito.MockitoAnnotations;
42 import org.opendaylight.protocol.concepts.KeyMapping;
43 import org.opendaylight.protocol.pcep.PCEPCapability;
44 import org.opendaylight.protocol.pcep.PCEPDispatcherDependencies;
45 import org.opendaylight.protocol.pcep.PCEPSession;
46 import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
47 import org.opendaylight.protocol.pcep.PCEPSessionNegotiatorFactory;
48 import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
49 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
50 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
51 import org.opendaylight.protocol.util.InetSocketAddressUtil;
53 public class PCEPDispatcherImplTest {
54 private static final short DEAD_TIMER = 120;
55 private static final short KEEP_ALIVE = 30;
56 private static final int RETRY_TIMER = 0;
57 private static final int CONNECT_TIMEOUT = 500;
59 private PCEPDispatcherImpl dispatcher;
60 private PCEPDispatcherImpl disp2Spy;
63 private Channel mockChannel;
65 private PCEPDispatcherDependencies dispatcherDependencies;
67 private PCEPSessionListenerFactory listenerFactory;
69 private PCCMock pccMock;
73 MockitoAnnotations.initMocks(this);
74 final List<PCEPCapability> capList = new ArrayList<>();
75 final PCEPSessionProposalFactory sessionProposal = new BasePCEPSessionProposalFactory(DEAD_TIMER, KEEP_ALIVE,
77 final EventLoopGroup eventLoopGroup;
78 if (Epoll.isAvailable()) {
79 eventLoopGroup = new EpollEventLoopGroup();
81 eventLoopGroup = new NioEventLoopGroup();
83 final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
84 .getMessageHandlerRegistry();
85 this.dispatcher = new PCEPDispatcherImpl(msgReg,
86 new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
87 eventLoopGroup, eventLoopGroup);
89 doReturn(KeyMapping.getKeyMapping()).when(this.dispatcherDependencies).getKeys();
90 doReturn(null).when(this.dispatcherDependencies).getPeerProposal();
92 doReturn("mockChannel").when(this.mockChannel).toString();
93 final PCEPDispatcherImpl dispatcher2 = new PCEPDispatcherImpl(msgReg,
94 new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
95 eventLoopGroup, eventLoopGroup);
96 this.disp2Spy = Mockito.spy(dispatcher2);
98 this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
99 new PCEPHandlerFactory(msgReg));
103 public void testCreateClientServer() throws InterruptedException, ExecutionException {
104 final int port = InetSocketAddressUtil.getRandomPort();
105 final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
106 final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
107 final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
109 doReturn(serverAddr).when(this.dispatcherDependencies).getAddress();
110 doReturn(this.listenerFactory).when(this.dispatcherDependencies).getListenerFactory();
111 doReturn(new SimpleSessionListener()).when(this.listenerFactory).getSessionListener();
112 final ChannelFuture futureChannel = this.dispatcher.createServer(this.dispatcherDependencies);
113 waitFutureSuccess(futureChannel);
114 final PCEPSessionImpl session1 = this.pccMock.createClient(clientAddr1,
115 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
117 final PCEPSessionImpl session2 = this.pccMock.createClient(clientAddr2,
118 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
120 Assert.assertTrue(futureChannel.channel().isActive());
121 assertEquals(clientAddr1.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
122 assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
123 assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
125 assertEquals(clientAddr2.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
126 assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
127 assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
131 Assert.assertTrue(futureChannel.channel().isActive());
135 public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
136 final int port = InetSocketAddressUtil.getRandomPort();
137 final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
138 final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
140 doReturn(serverAddr).when(this.dispatcherDependencies).getAddress();
141 doReturn(this.listenerFactory).when(this.dispatcherDependencies).getListenerFactory();
142 doReturn(new SimpleSessionListener()).when(this.listenerFactory).getSessionListener();
144 waitFutureSuccess(this.dispatcher.createServer(this.dispatcherDependencies));
145 final Future<PCEPSessionImpl> futureClient = this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
146 SimpleSessionListener::new);
147 waitFutureSuccess(futureClient);
148 final PCEPSessionImpl session1 = futureClient.get();
151 this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
152 SimpleSessionListener::new).get();
154 } catch (final ExecutionException e) {
155 Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
162 public void testReconectClient() throws InterruptedException, ExecutionException {
163 final int port = InetSocketAddressUtil.getRandomPort();
164 final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
166 doReturn(new InetSocketAddress("0.0.0.0", port)).when(this.dispatcherDependencies).getAddress();
167 doReturn(this.listenerFactory).when(this.dispatcherDependencies).getListenerFactory();
168 doReturn(new SimpleSessionListener()).when(this.listenerFactory).getSessionListener();
169 waitFutureSuccess(this.dispatcher.createServer(this.dispatcherDependencies));
170 final PCEPSessionImpl session1 = this.pccMock.createClient(clientAddr,
171 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
173 assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
174 assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
175 assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
176 waitFutureSuccess(session1.closeChannel());
178 final PCEPSessionImpl session2 = this.pccMock.createClient(clientAddr,
179 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
181 assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
182 assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
183 assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
189 public void testCustomizeBootstrap() {
190 final int port = InetSocketAddressUtil.getRandomPort();
191 final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
192 final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
193 final KeyMapping keys = KeyMapping.getKeyMapping(clientAddr1.getAddress(), "CLIENT1_ADDRESS");
194 keys.put(clientAddr2.getAddress(), "CLIENT2_ADDRESS".getBytes());
196 doReturn(new InetSocketAddress("0.0.0.0", port)).when(this.dispatcherDependencies).getAddress();
197 doReturn(this.listenerFactory).when(this.dispatcherDependencies).getListenerFactory();
198 doReturn(new SimpleSessionListener()).when(this.listenerFactory).getSessionListener();
200 final ChannelFuture futureChannel = this.disp2Spy.createServer(this.dispatcherDependencies);
201 waitFutureSuccess(futureChannel);
202 Mockito.verify(this.disp2Spy).createServerBootstrap(any(PCEPDispatcherImpl.ChannelPipelineInitializer.class));
206 public void tearDown() {
207 this.dispatcher.close();
208 this.disp2Spy.close();
211 private static class PCCMock {
212 private final PCEPSessionNegotiatorFactory<PCEPSessionImpl> negotiatorFactory;
213 private final PCEPHandlerFactory factory;
214 private final EventExecutor executor;
215 private final EventLoopGroup workerGroup;
217 PCCMock(final PCEPSessionNegotiatorFactory<PCEPSessionImpl> negotiatorFactory,
218 final PCEPHandlerFactory factory) {
219 this.workerGroup = new NioEventLoopGroup();
220 this.negotiatorFactory = requireNonNull(negotiatorFactory);
221 this.factory = requireNonNull(factory);
222 this.executor = requireNonNull(GlobalEventExecutor.INSTANCE);
225 Future<PCEPSessionImpl> createClient(final InetSocketAddress address, final int retryTimer,
226 final int connectTimeout, final PCEPSessionListenerFactory listenerFactory) {
227 return createClient(address, retryTimer, connectTimeout, (ch, promise) -> {
228 ch.pipeline().addLast(this.factory.getDecoders());
229 ch.pipeline().addLast("negotiator", this.negotiatorFactory.getSessionNegotiator(
230 () -> listenerFactory,
233 ch.pipeline().addLast(this.factory.getEncoders());
237 Future<PCEPSessionImpl> createClient(final InetSocketAddress address, final int retryTimer,
238 final int connectTimeout, final PCEPDispatcherImpl.ChannelPipelineInitializer initializer) {
239 final Bootstrap b = new Bootstrap();
240 final PCEPProtocolSessionPromise<PCEPSessionImpl> p = new PCEPProtocolSessionPromise<>(this.executor,
241 address, retryTimer, connectTimeout, b);
242 b.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE).handler(new ChannelInitializer<SocketChannel>() {
244 protected void initChannel(final SocketChannel ch) {
245 initializer.initializeChannel(ch, p);
250 setChannelFactory(b);
255 private static void setChannelFactory(final Bootstrap b) {
257 b.channel(NioSocketChannel.class);
258 } catch (final IllegalStateException ignored) {
262 private void setWorkerGroup(final Bootstrap b) {
263 if (b.config().group() == null) {
264 b.group(this.workerGroup);