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 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;
48 public class PCEPDispatcherImplTest {
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;
58 private PCEPDispatcherImpl dispatcher;
59 private PCEPDispatcherImpl disp2Spy;
61 @Mock 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, capList);
70 final EventLoopGroup eventLoopGroup;
71 if (Epoll.isAvailable()) {
72 eventLoopGroup = new EpollEventLoopGroup();
74 eventLoopGroup = new NioEventLoopGroup();
76 final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
77 .getMessageHandlerRegistry();
78 this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
79 eventLoopGroup, eventLoopGroup);
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);
85 this.pccMock = new PCCMock(new DefaultPCEPSessionNegotiatorFactory(sessionProposal, 0),
86 new PCEPHandlerFactory(msgReg), new DefaultPromise<PCEPSessionImpl>(
87 GlobalEventExecutor.INSTANCE));
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();
98 final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT2_ADDRESS,
99 RETRY_TIMER, CONNECT_TIMEOUT,
100 () -> new SimpleSessionListener()).get();
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());
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());
113 Assert.assertTrue(futureChannel.channel().isActive());
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();
125 this.pccMock.createClient(CLIENT1_ADDRESS, RETRY_TIMER, CONNECT_TIMEOUT,
126 () -> new SimpleSessionListener()).get();
128 } catch (final ExecutionException e) {
129 Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
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();
143 Assert.assertEquals(CLIENT1_ADDRESS.getAddress(), session1.getRemoteAddress());
144 Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
145 Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
148 final PCEPSessionImpl session2 = (PCEPSessionImpl) this.pccMock.createClient(CLIENT1_ADDRESS,
149 RETRY_TIMER, CONNECT_TIMEOUT,
150 () -> new SimpleSessionListener()).get();
152 Assert.assertEquals(CLIENT1_ADDRESS.getAddress(), session1.getRemoteAddress());
153 Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
154 Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
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() );
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));
170 public void tearDown() {
171 this.dispatcher.close();
172 this.disp2Spy.close();
175 private static class PCCMock {
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;
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);
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());
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>() {
207 protected void initChannel(final SocketChannel ch) {
208 initializer.initializeChannel(ch, p);
213 setChannelFactory(b);
218 private void setChannelFactory(final Bootstrap b) {
220 b.channel(NioSocketChannel.class);
221 } catch (final IllegalStateException ignored) {
226 private void setWorkerGroup(final Bootstrap b) {
227 if (b.group() == null) {
228 b.group(this.workerGroup);