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.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
16 import io.netty.bootstrap.Bootstrap;
17 import io.netty.channel.ChannelFuture;
18 import io.netty.channel.ChannelInitializer;
19 import io.netty.channel.ChannelOption;
20 import io.netty.channel.EventLoopGroup;
21 import io.netty.channel.epoll.Epoll;
22 import io.netty.channel.epoll.EpollEventLoopGroup;
23 import io.netty.channel.nio.NioEventLoopGroup;
24 import io.netty.channel.socket.SocketChannel;
25 import io.netty.channel.socket.nio.NioSocketChannel;
26 import io.netty.util.concurrent.EventExecutor;
27 import io.netty.util.concurrent.Future;
28 import io.netty.util.concurrent.GlobalEventExecutor;
29 import java.net.InetSocketAddress;
30 import java.nio.channels.Channel;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.ExecutionException;
34 import org.junit.After;
35 import org.junit.Assert;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.mockito.Mock;
39 import org.mockito.Mockito;
40 import org.mockito.MockitoAnnotations;
41 import org.opendaylight.protocol.concepts.KeyMapping;
42 import org.opendaylight.protocol.pcep.PCEPCapability;
43 import org.opendaylight.protocol.pcep.PCEPSession;
44 import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
45 import org.opendaylight.protocol.pcep.PCEPSessionNegotiatorFactory;
46 import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
47 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
48 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
49 import org.opendaylight.protocol.util.InetSocketAddressUtil;
51 public class PCEPDispatcherImplTest {
52 private static final short DEAD_TIMER = 120;
53 private static final short KEEP_ALIVE = 30;
54 private static final int RETRY_TIMER = 0;
55 private static final int CONNECT_TIMEOUT = 500;
57 private PCEPDispatcherImpl dispatcher;
58 private PCEPDispatcherImpl disp2Spy;
61 private Channel mockChannel;
63 private PCCMock pccMock;
67 MockitoAnnotations.initMocks(this);
68 final List<PCEPCapability> capList = new ArrayList<>();
69 final PCEPSessionProposalFactory sessionProposal = new BasePCEPSessionProposalFactory(DEAD_TIMER, KEEP_ALIVE,
71 final EventLoopGroup eventLoopGroup;
72 if (Epoll.isAvailable()) {
73 eventLoopGroup = new EpollEventLoopGroup();
75 eventLoopGroup = new NioEventLoopGroup();
77 final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
78 .getMessageHandlerRegistry();
79 this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
80 eventLoopGroup, eventLoopGroup);
82 Mockito.doReturn("mockChannel").when(this.mockChannel).toString();
83 final PCEPDispatcherImpl dispatcher2 = new PCEPDispatcherImpl(msgReg,
84 new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
85 eventLoopGroup, eventLoopGroup);
86 this.disp2Spy = Mockito.spy(dispatcher2);
88 this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
89 new PCEPHandlerFactory(msgReg));
93 public void testCreateClientServer() throws InterruptedException, ExecutionException {
94 final int port = InetSocketAddressUtil.getRandomPort();
95 final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
96 final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
97 final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
98 final ChannelFuture futureChannel = this.dispatcher.createServer(serverAddr,
99 SimpleSessionListener::new, null);
100 waitFutureSuccess(futureChannel);
101 final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr1,
102 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
104 final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr2,
105 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
107 Assert.assertTrue(futureChannel.channel().isActive());
108 assertEquals(clientAddr1.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
109 assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
110 assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
112 assertEquals(clientAddr2.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
113 assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
114 assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
118 Assert.assertTrue(futureChannel.channel().isActive());
122 public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
123 final int port = InetSocketAddressUtil.getRandomPort();
124 final InetSocketAddress serverAddr = new InetSocketAddress("0.0.0.0", port);
125 final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
126 waitFutureSuccess(this.dispatcher.createServer(serverAddr, SimpleSessionListener::new, null));
127 final Future<PCEPSession> futureClient = this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
128 SimpleSessionListener::new);
129 waitFutureSuccess(futureClient);
130 final PCEPSessionImpl session1 = (PCEPSessionImpl) futureClient.get();
133 this.pccMock.createClient(clientAddr, RETRY_TIMER, CONNECT_TIMEOUT,
134 SimpleSessionListener::new).get();
136 } catch (final ExecutionException e) {
137 Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
144 public void testReconectClient() throws InterruptedException, ExecutionException {
145 final int port = InetSocketAddressUtil.getRandomPort();
146 final InetSocketAddress clientAddr = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
147 waitFutureSuccess(this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", port),
148 SimpleSessionListener::new, null));
149 final PCEPSessionImpl session1 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
150 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
152 assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
153 assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
154 assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
155 waitFutureSuccess(session1.closeChannel());
157 final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(clientAddr,
158 RETRY_TIMER, CONNECT_TIMEOUT, SimpleSessionListener::new).get();
160 assertEquals(clientAddr.getAddress(), session1.getRemoteAddress());
161 assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
162 assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
168 public void testCustomizeBootstrap() {
169 final int port = InetSocketAddressUtil.getRandomPort();
170 final InetSocketAddress clientAddr1 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
171 final InetSocketAddress clientAddr2 = InetSocketAddressUtil.getRandomLoopbackInetSocketAddress(port);
172 final KeyMapping keys = KeyMapping.getKeyMapping(clientAddr1.getAddress(), "CLIENT1_ADDRESS");
173 keys.put(clientAddr2.getAddress(), "CLIENT2_ADDRESS".getBytes());
175 final ChannelFuture futureChannel = this.disp2Spy.createServer(new InetSocketAddress("0.0.0.0", port),
176 SimpleSessionListener::new, null);
177 waitFutureSuccess(futureChannel);
178 Mockito.verify(this.disp2Spy).createServerBootstrap(any(PCEPDispatcherImpl.ChannelPipelineInitializer.class));
182 public void tearDown() {
183 this.dispatcher.close();
184 this.disp2Spy.close();
187 private static class PCCMock {
188 private final PCEPSessionNegotiatorFactory negotiatorFactory;
189 private final PCEPHandlerFactory factory;
190 private final EventExecutor executor;
191 private final EventLoopGroup workerGroup;
193 PCCMock(final PCEPSessionNegotiatorFactory<?> negotiatorFactory, final PCEPHandlerFactory factory) {
194 this.workerGroup = requireNonNull(new NioEventLoopGroup());
195 this.negotiatorFactory = requireNonNull(negotiatorFactory);
196 this.factory = requireNonNull(factory);
197 this.executor = requireNonNull(GlobalEventExecutor.INSTANCE);
200 Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
201 final int connectTimeout, final PCEPSessionListenerFactory listenerFactory) {
202 return createClient(address, retryTimer, connectTimeout, (ch, promise) -> {
203 ch.pipeline().addLast(this.factory.getDecoders());
204 ch.pipeline().addLast("negotiator", this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch,
206 ch.pipeline().addLast(this.factory.getEncoders());
210 Future<PCEPSession> createClient(final InetSocketAddress address, final int retryTimer,
211 final int connectTimeout, final PCEPDispatcherImpl.ChannelPipelineInitializer initializer) {
212 final Bootstrap b = new Bootstrap();
213 final PCEPProtocolSessionPromise p = new PCEPProtocolSessionPromise<>(this.executor, address, retryTimer,
215 b.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE).handler(new ChannelInitializer<SocketChannel>() {
217 protected void initChannel(final SocketChannel ch) {
218 initializer.initializeChannel(ch, p);
223 setChannelFactory(b);
228 private static void setChannelFactory(final Bootstrap b) {
230 b.channel(NioSocketChannel.class);
231 } catch (final IllegalStateException ignored) {
235 private void setWorkerGroup(final Bootstrap b) {
236 if (b.group() == null) {
237 b.group(this.workerGroup);