BUG-9079 Make PCEP session recoverable from exception
[bgpcep.git] / pcep / topology / topology-provider / src / test / java / org / opendaylight / bgpcep / pcep / topology / provider / AbstractPCEPSessionTest.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.bgpcep.pcep.topology.provider;
10
11 import static org.junit.Assert.assertFalse;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import static org.opendaylight.protocol.util.CheckUtil.checkEquals;
18
19 import com.google.common.util.concurrent.ListenableFuture;
20 import io.netty.channel.Channel;
21 import io.netty.channel.ChannelFuture;
22 import io.netty.channel.ChannelHandler;
23 import io.netty.channel.ChannelPipeline;
24 import io.netty.channel.EventLoop;
25 import io.netty.util.concurrent.Promise;
26 import java.lang.reflect.ParameterizedType;
27 import java.net.InetSocketAddress;
28 import java.net.SocketAddress;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.TimeUnit;
32 import org.junit.After;
33 import org.junit.Before;
34 import org.mockito.Mock;
35 import org.mockito.Mockito;
36 import org.mockito.MockitoAnnotations;
37 import org.opendaylight.controller.config.yang.pcep.topology.provider.ListenerStateRuntimeMXBean;
38 import org.opendaylight.controller.config.yang.pcep.topology.provider.ListenerStateRuntimeRegistration;
39 import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeMXBean;
40 import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeRegistration;
41 import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeRegistrator;
42 import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
43 import org.opendaylight.protocol.pcep.PCEPSessionListener;
44 import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiator;
45 import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
46 import org.opendaylight.protocol.util.InetSocketAddressUtil;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.opendaylight.yangtools.yang.binding.Notification;
70
71 public abstract class AbstractPCEPSessionTest<T extends TopologySessionListenerFactory>
72     extends AbstractConcurrentDataBrokerTest {
73
74     private static final String TEST_TOPOLOGY_NAME = "testtopo";
75     static final InstanceIdentifier<Topology> TOPO_IID = InstanceIdentifier.builder(NetworkTopology.class).child(
76             Topology.class, new TopologyKey(new TopologyId(TEST_TOPOLOGY_NAME))).build();
77     private static final String IPV4_MASK = "/32";
78     static final short DEAD_TIMER = 30;
79     static final short KEEP_ALIVE = 10;
80     static final short RPC_TIMEOUT = 4;
81
82     final String testAddress = InetSocketAddressUtil.getRandomLoopbackIpAddress();
83     final NodeId nodeId = new NodeId("pcc://" + this.testAddress);
84     protected final InstanceIdentifier<PathComputationClient> pathComputationClientIId = TOPO_IID.builder()
85         .child(Node.class, new NodeKey(this.nodeId)).augmentation(Node1.class).child(PathComputationClient.class
86         ).build();
87     final String eroIpPrefix = this.testAddress + IPV4_MASK;
88     final String newDestinationAddress = InetSocketAddressUtil.getRandomLoopbackIpAddress();
89     final String dstIpPrefix = this.newDestinationAddress + IPV4_MASK;
90
91     List<Notification> receivedMsgs;
92
93     @Mock
94     private EventLoop eventLoop;
95
96     @Mock
97     private Channel clientListener;
98
99     @Mock
100     private ChannelPipeline pipeline;
101
102     @Mock
103     private ChannelFuture channelFuture;
104
105     @Mock
106     ListenerStateRuntimeRegistration listenerReg;
107
108     @Mock
109     private PCEPTopologyProviderRuntimeRegistrator registrator;
110
111     private final Open localPrefs = new OpenBuilder().setDeadTimer((short) 30).setKeepalive((short) 10)
112         .setSessionId((short) 0).build();
113
114     private final Open remotePrefs = this.localPrefs;
115
116     ServerSessionManager manager;
117
118     NetworkTopologyPcepService topologyRpcs;
119
120     private DefaultPCEPSessionNegotiator neg;
121
122     @Before
123     public void setUp() throws Exception {
124         MockitoAnnotations.initMocks(this);
125         this.receivedMsgs = new ArrayList<>();
126         doAnswer(invocation -> {
127             final Object[] args = invocation.getArguments();
128             AbstractPCEPSessionTest.this.receivedMsgs.add((Notification) args[0]);
129             return this.channelFuture;
130         }).when(this.clientListener).writeAndFlush(any(Notification.class));
131         doReturn(null).when(this.channelFuture).addListener(Mockito.any());
132         doReturn("TestingChannel").when(this.clientListener).toString();
133         doReturn(this.pipeline).when(this.clientListener).pipeline();
134         doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class),
135             any(ChannelHandler.class));
136         doReturn(this.eventLoop).when(this.clientListener).eventLoop();
137         doReturn(null).when(this.eventLoop).schedule(any(Runnable.class), any(long.class),
138             any(TimeUnit.class));
139         doReturn(true).when(this.clientListener).isActive();
140         final SocketAddress ra = new InetSocketAddress(this.testAddress, 4189);
141         doReturn(ra).when(this.clientListener).remoteAddress();
142         final SocketAddress la = new InetSocketAddress(this.testAddress, InetSocketAddressUtil.getRandomPort());
143         doReturn(la).when(this.clientListener).localAddress();
144
145         doReturn(mock(ChannelFuture.class)).when(this.clientListener).close();
146
147         doNothing().when(this.listenerReg).close();
148         doReturn("listenerReg").when(this.listenerReg).toString();
149         final PCEPTopologyProviderRuntimeRegistration topologyReg = mock(PCEPTopologyProviderRuntimeRegistration.class);
150         doReturn(this.listenerReg).when(topologyReg).register(any(ListenerStateRuntimeMXBean.class));
151         doNothing().when(topologyReg).close();
152         doReturn(topologyReg).when(this.registrator).register(any(PCEPTopologyProviderRuntimeMXBean.class));
153
154         final T listenerFactory = (T) ((Class) ((ParameterizedType) this.getClass().getGenericSuperclass())
155             .getActualTypeArguments()[0]).newInstance();
156         this.manager = new ServerSessionManager(getDataBroker(), TOPO_IID, listenerFactory, RPC_TIMEOUT);
157         startSessionManager();
158         this.neg = new DefaultPCEPSessionNegotiator(mock(Promise.class), this.clientListener,
159             this.manager.getSessionListener(), (short) 1, 5, this.localPrefs);
160         this.topologyRpcs = new TopologyRPCs(this.manager);
161     }
162
163     protected void startSessionManager() throws Exception {
164         this.manager.setRuntimeRootRegistrator(this.registrator);
165         final ListenableFuture<Void> future = this.manager.instantiateServiceInstance();
166         future.get();
167         checkEquals(()-> assertFalse(this.manager.isClosed.get()));
168     }
169
170     protected void stopSessionManager() {
171         this.manager.closeServiceInstance();
172     }
173
174     @After
175     public void tearDown() {
176         stopSessionManager();
177     }
178
179     Ero createEroWithIpPrefixes(final List<String> ipPrefixes) {
180         final List<Subobject> subobjs = new ArrayList<>(ipPrefixes.size());
181         final SubobjectBuilder subobjBuilder = new SubobjectBuilder();
182         for (final String ipPrefix : ipPrefixes) {
183             subobjBuilder.setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder().setIpPrefix(
184                 new IpPrefix(new Ipv4Prefix(ipPrefix))).build()).build());
185             subobjs.add(subobjBuilder.build());
186         }
187         return new EroBuilder().setSubobject(subobjs).build();
188     }
189
190     String getLastEroIpPrefix(final Ero ero) {
191         return ((IpPrefixCase)ero.getSubobject().get(ero.getSubobject().size() - 1).getSubobjectType()).getIpPrefix()
192             .getIpPrefix().getIpv4Prefix().getValue();
193     }
194
195     protected Open getLocalPref() {
196         return this.localPrefs;
197     }
198
199     protected Open getRemotePref() {
200         return this.remotePrefs;
201     }
202
203     protected PCEPSessionListener getSessionListener() {
204         return this.manager.getSessionListener();
205     }
206
207     protected final PCEPSessionImpl getPCEPSession(final Open localOpen, final Open remoteOpen) {
208         return this.neg.createSession(this.clientListener, localOpen, remoteOpen);
209     }
210 }