Create pcep topology parent aggregator
[bgpcep.git] / pcep / topology / topology-provider / src / test / java / org / opendaylight / bgpcep / pcep / topology / provider / Stateful07TopologySessionListenerTest.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.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17 import static org.mockito.Mockito.times;
18 import static org.mockito.Mockito.verify;
19 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createLspTlvs;
20 import static org.opendaylight.protocol.util.CheckUtil.checkEquals;
21 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
22 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
23 import com.google.common.base.Optional;
24 import com.google.common.collect.Lists;
25 import java.net.UnknownHostException;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.Future;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.TimeoutException;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.opendaylight.controller.config.yang.pcep.topology.provider.SessionState;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
37 import org.opendaylight.protocol.pcep.PCEPCloseTermination;
38 import org.opendaylight.protocol.pcep.TerminationReason;
39 import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
40 import org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil;
41 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
42 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
43 import org.opendaylight.protocol.util.CheckUtil;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.topology.rev140113.NetworkTopologyRef;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1Builder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments1;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments1Builder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments2;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments2Builder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments3;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments3Builder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcrptBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SymbolicPathName;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.LspIdentifiersBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.PcrptMessageBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.Reports;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.ReportsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.PathBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Close;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4CaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.ipv4._case.Ipv4Builder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.EndpointsObjBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObject;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.LspId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInputBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInputBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.FailureType;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInputBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInputBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.add.lsp.args.ArgumentsBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.Path;
100 import org.opendaylight.yangtools.yang.common.RpcResult;
101
102 public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTest<Stateful07TopologySessionListenerFactory> {
103
104     private final String TUNNEL_NAME = "pcc_" + this.testAddress + "_tunnel_0";
105
106     private Stateful07TopologySessionListener listener;
107
108     private PCEPSessionImpl session;
109
110     @Override
111     @Before
112     public void setUp() throws Exception {
113         super.setUp();
114         this.listener = (Stateful07TopologySessionListener) getSessionListener();
115         this.session = getPCEPSession(getLocalPref(), getRemotePref());
116     }
117
118     @Test
119     public void testStateful07TopologySessionListener() throws Exception {
120         this.listener.onSessionUp(this.session);
121
122         assertEquals(this.testAddress, this.listener.getPeerId());
123         final SessionState state = this.listener.getSessionState();
124         assertNotNull(state);
125         assertEquals(DEAD_TIMER, state.getLocalPref().getDeadtimer().shortValue());
126         assertEquals(KEEP_ALIVE, state.getLocalPref().getKeepalive().shortValue());
127         assertEquals(0, state.getLocalPref().getSessionId().intValue());
128         assertEquals(this.testAddress, state.getLocalPref().getIpAddress());
129         assertEquals(DEAD_TIMER, state.getPeerPref().getDeadtimer().shortValue());
130         assertEquals(KEEP_ALIVE, state.getPeerPref().getKeepalive().shortValue());
131         assertEquals(0, state.getPeerPref().getSessionId().intValue());
132         assertEquals(this.testAddress, state.getPeerPref().getIpAddress());
133
134         // add-lsp
135         this.topologyRpcs.addLsp(createAddLspInput());
136         assertEquals(1, this.receivedMsgs.size());
137         assertTrue(this.receivedMsgs.get(0) instanceof Pcinitiate);
138         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
139         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
140         final long srpId = req.getSrp().getOperationId().getValue();
141         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
142             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
143         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp())
144             .setTlvs(tlvs).setPlspId(new PlspId(1L)).setSync(false).setRemove(false)
145             .setOperational(OperationalStatus.Active).build(), Optional.of(MsgBuilderUtil.createSrp(srpId)),
146             MsgBuilderUtil.createPath(req.getEro().getSubobject()));
147         final Pcrpt esm = MsgBuilderUtil.createPcRtpMessage(new LspBuilder().setSync(false).build(),
148             Optional.of(MsgBuilderUtil.createSrp(0L)), null);
149         this.listener.onMessage(this.session, esm);
150         readDataOperational(getDataBroker(), this.pathComputationClientIId, pcc -> {
151             assertEquals(this.testAddress, pcc.getIpAddress().getIpv4Address().getValue());
152             // reported lsp so far empty, has not received response (PcRpt) yet
153             assertTrue(pcc.getReportedLsp().isEmpty());
154             return pcc;
155         });
156
157         this.listener.onMessage(this.session, pcRpt);
158         // check created lsp
159         readDataOperational(getDataBroker(), this.pathComputationClientIId, pcc -> {
160             assertEquals(1, pcc.getReportedLsp().size());
161             final ReportedLsp reportedLsp = pcc.getReportedLsp().get(0);
162             assertEquals(this.TUNNEL_NAME, reportedLsp.getName());
163             assertEquals(1, reportedLsp.getPath().size());
164             final Path path = reportedLsp.getPath().get(0);
165             assertEquals(1, path.getEro().getSubobject().size());
166             assertEquals(this.eroIpPrefix, getLastEroIpPrefix(path.getEro()));
167             return pcc;
168         });
169
170         // check stats
171         checkEquals(()->assertEquals(1, this.listener.getDelegatedLspsCount().intValue()));
172         checkEquals(()->assertTrue(this.listener.getSynchronized()));
173         checkEquals(()->assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0));
174         checkEquals(()->assertEquals(2, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue()));
175         checkEquals(()->assertEquals(1, this.listener.getStatefulMessages().getSentInitMsgCount().intValue()));
176         checkEquals(()->assertEquals(0, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue()));
177         checkEquals(()->assertNotNull(this.listener.getSessionState()));
178
179         // update-lsp
180         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args
181             .ArgumentsBuilder updArgsBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.
182             topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder();
183         updArgsBuilder.setEro(createEroWithIpPrefixes(Lists.newArrayList(this.eroIpPrefix, this.dstIpPrefix)));
184         updArgsBuilder.addAugmentation(Arguments3.class, new Arguments3Builder().setLsp(new LspBuilder()
185             .setDelegate(true).setAdministrative(true).build()).build());
186         final UpdateLspInput update = new UpdateLspInputBuilder().setArguments(updArgsBuilder.build())
187             .setName(this.TUNNEL_NAME).setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID))
188             .setNode(this.nodeId).build();
189         this.topologyRpcs.updateLsp(update);
190         assertEquals(2, this.receivedMsgs.size());
191         assertTrue(this.receivedMsgs.get(1) instanceof Pcupd);
192         final Pcupd updateMsg = (Pcupd) this.receivedMsgs.get(1);
193         final Updates upd = updateMsg.getPcupdMessage().getUpdates().get(0);
194         final long srpId2 = upd.getSrp().getOperationId().getValue();
195         final Tlvs tlvs2 = createLspTlvs(upd.getLsp().getPlspId().getValue(), false,
196             this.newDestinationAddress, this.testAddress, this.testAddress, Optional.absent());
197         final Pcrpt pcRpt2 = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(upd.getLsp()).setTlvs(tlvs2)
198             .setSync(true).setRemove(false).setOperational(OperationalStatus.Active).build(),
199             Optional.of(MsgBuilderUtil.createSrp(srpId2)), MsgBuilderUtil.createPath(upd.getPath()
200                 .getEro().getSubobject()));
201         this.listener.onMessage(this.session, pcRpt2);
202
203         //check updated lsp
204         readDataOperational(getDataBroker(), this.pathComputationClientIId, pcc -> {
205             assertEquals(1, pcc.getReportedLsp().size());
206             final ReportedLsp reportedLsp = pcc.getReportedLsp().get(0);
207             assertEquals(this.TUNNEL_NAME, reportedLsp.getName());
208             assertEquals(1, reportedLsp.getPath().size());
209             final Path path = reportedLsp.getPath().get(0);
210             assertEquals(2, path.getEro().getSubobject().size());
211             assertEquals(this.dstIpPrefix, getLastEroIpPrefix(path.getEro()));
212             assertEquals(1, this.listener.getDelegatedLspsCount().intValue());
213             assertTrue(this.listener.getSynchronized());
214             assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0);
215             assertEquals(3, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue());
216             assertEquals(1, this.listener.getStatefulMessages().getSentInitMsgCount().intValue());
217             assertEquals(1, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue());
218             assertTrue(this.listener.getReplyTime().getAverageTime() > 0);
219             assertTrue(this.listener.getReplyTime().getMaxTime() > 0);
220             assertFalse(this.listener.getPeerCapabilities().getActive());
221             assertTrue(this.listener.getPeerCapabilities().getInstantiation());
222             assertTrue(this.listener.getPeerCapabilities().getStateful());
223             return pcc;
224         });
225
226         // ensure-operational
227         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.ensure.lsp.
228             operational.args.ArgumentsBuilder ensureArgs = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.
229             xml.ns.yang.topology.pcep.rev131024.ensure.lsp.operational.args.ArgumentsBuilder();
230         ensureArgs.addAugmentation(Arguments1.class, new Arguments1Builder().setOperational(OperationalStatus.Active)
231             .build());
232         final EnsureLspOperationalInput ensure = new EnsureLspOperationalInputBuilder().setArguments(ensureArgs.build())
233             .setName(this.TUNNEL_NAME).setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID))
234             .setNode(this.nodeId).build();
235         final OperationResult result = this.topologyRpcs.ensureLspOperational(ensure).get().getResult();
236         //check result
237         assertNull(result.getFailure());
238
239         // remove-lsp
240         final RemoveLspInput remove = new RemoveLspInputBuilder().setName(this.TUNNEL_NAME)
241             .setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID)).setNode(this.nodeId).build();
242         this.topologyRpcs.removeLsp(remove);
243         assertEquals(3, this.receivedMsgs.size());
244         assertTrue(this.receivedMsgs.get(2) instanceof Pcinitiate);
245         final Pcinitiate pcinitiate2 = (Pcinitiate) this.receivedMsgs.get(2);
246         final Requests req2 = pcinitiate2.getPcinitiateMessage().getRequests().get(0);
247         final long srpId3 = req2.getSrp().getOperationId().getValue();
248         final Tlvs tlvs3 = createLspTlvs(req2.getLsp().getPlspId().getValue(), false,
249             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
250         final Pcrpt pcRpt3 = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req2.getLsp()).setTlvs(tlvs3)
251             .setRemove(true).setSync(true).setOperational(OperationalStatus.Down).build(),
252             Optional.of(MsgBuilderUtil.createSrp(srpId3)), MsgBuilderUtil.createPath(Collections.emptyList()));
253         this.listener.onMessage(this.session, pcRpt3);
254
255         // check if lsp was removed
256         readDataOperational(getDataBroker(), this.pathComputationClientIId, pcc -> {
257             assertEquals(0, pcc.getReportedLsp().size());
258             return pcc;
259         });
260         // check stats
261         checkEquals(()->assertEquals(0, this.listener.getDelegatedLspsCount().intValue()));
262         checkEquals(()->assertTrue(this.listener.getSynchronized()));
263         checkEquals(()->assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0));
264         checkEquals(()->assertEquals(4, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue()));
265         checkEquals(()->assertEquals(2, this.listener.getStatefulMessages().getSentInitMsgCount().intValue()));
266         checkEquals(()->assertEquals(1, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue()));
267         checkEquals(()->this.listener.resetStats());
268         checkEquals(()->assertEquals(0, this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp().longValue()));
269         checkEquals(()->assertEquals(0, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue()));
270         checkEquals(()->assertEquals(0, this.listener.getStatefulMessages().getSentInitMsgCount().intValue()));
271         checkEquals(()->assertEquals(0, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue()));
272         checkEquals(()->assertEquals(0, this.listener.getReplyTime().getAverageTime().longValue()));
273         checkEquals(()->assertEquals(0, this.listener.getReplyTime().getMaxTime().longValue()));
274         checkEquals(()->assertEquals(0, this.listener.getReplyTime().getMinTime().longValue()));
275     }
276
277     @Test
278     public void testOnUnhandledErrorMessage() {
279         final Message errorMsg = AbstractMessageParser.createErrorMsg(PCEPErrors.NON_ZERO_PLSPID, Optional.absent());
280         this.listener.onSessionUp(this.session);
281         assertTrue(this.listener.onMessage(Optional.<AbstractTopologySessionListener.MessageContext>absent().orNull(), errorMsg));
282     }
283
284     @Test
285     public void testOnErrorMessage() throws InterruptedException, ExecutionException {
286         final Message errorMsg = MsgBuilderUtil.createErrorMsg(PCEPErrors.NON_ZERO_PLSPID, 1L);
287         this.listener.onSessionUp(this.session);
288         final Future<RpcResult<AddLspOutput>> futureOutput = this.topologyRpcs.addLsp(createAddLspInput());
289         this.listener.onMessage(this.session, errorMsg);
290
291         final AddLspOutput output = futureOutput.get().getResult();
292         assertEquals(FailureType.Failed ,output.getFailure());
293         assertEquals(1, output.getError().size());
294         final ErrorObject err = output.getError().get(0).getErrorObject();
295         assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorType(), err.getType().shortValue());
296         assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorValue(), err.getValue().shortValue());
297     }
298
299     @Test
300     public void testOnSessionDown() throws InterruptedException, ExecutionException {
301         this.listener.onSessionUp(this.session);
302         verify(this.listenerReg, times(0)).close();
303         // send request
304         final Future<RpcResult<AddLspOutput>> futureOutput = this.topologyRpcs.addLsp(createAddLspInput());
305         assertFalse(this.session.isClosed());
306         this.listener.onSessionDown(this.session, new IllegalArgumentException());
307         assertTrue(this.session.isClosed());
308         verify(this.listenerReg, times(1)).close();
309         final AddLspOutput output = futureOutput.get().getResult();
310         // deal with unsent request after session down
311         assertEquals(FailureType.Unsent, output.getFailure());
312     }
313
314     /**
315      * All the pcep session registration should be closed when the session manager is closed
316      * @throws InterruptedException
317      * @throws ExecutionException
318      * @throws TransactionCommitFailedException
319      */
320     @Test
321     public void testOnServerSessionManagerDown() throws InterruptedException, ExecutionException,
322         TransactionCommitFailedException {
323         this.listener.onSessionUp(this.session);
324         // the session should not be closed when session manager is up
325         assertFalse(this.session.isClosed());
326         verify(this.listenerReg, times(0)).close();
327         // send request
328         final Future<RpcResult<AddLspOutput>> futureOutput = this.topologyRpcs.addLsp(createAddLspInput());
329         stopSessionManager();
330         verify(this.listenerReg, times(1)).close();
331         final AddLspOutput output = futureOutput.get().getResult();
332         // deal with unsent request after session down
333         assertEquals(FailureType.Unsent, output.getFailure());
334         // verify the session is closed after server session manager is closed
335         assertTrue(this.session.isClosed());
336     }
337
338     /**
339      * Verify the PCEP session should not be up when server session manager is down,
340      * otherwise it would be a problem when the session is up while it's not registered with session manager
341      * @throws InterruptedException
342      * @throws ExecutionException
343      * @throws TransactionCommitFailedException
344      */
345     @Test
346     public void testOnServerSessionManagerUnstarted() throws InterruptedException, ExecutionException,
347         TransactionCommitFailedException, ReadFailedException {
348         stopSessionManager();
349         // the registration should not be closed since it's never initialized
350         verify(this.listenerReg, times(0)).close();
351         assertFalse(this.session.isClosed());
352         this.listener.onSessionUp(this.session);
353         // verify the session was NOT added to topology
354         checkNotPresentOperational(getDataBroker(), TOPO_IID);
355         // still, the session should not be registered and thus close() is never called
356         verify(this.listenerReg, times(0)).close();
357         // verify the session is closed due to server session manager is closed
358         assertTrue(this.session.isClosed());
359         // send request
360         final Future<RpcResult<AddLspOutput>> futureOutput = this.topologyRpcs.addLsp(createAddLspInput());
361         final AddLspOutput output = futureOutput.get().getResult();
362         // deal with unsent request after session down
363         assertEquals(FailureType.Unsent, output.getFailure());
364     }
365
366     @Test
367     public void testOnServerSessionManagerRestartAndSessionRecovery() throws Exception {
368         // close server session manager first
369         stopSessionManager();
370         // the registration should not be closed since it's never initialized
371         verify(this.listenerReg, times(0)).close();
372         assertFalse(this.session.isClosed());
373         this.listener.onSessionUp(this.session);
374         // verify the session was NOT added to topology
375         checkNotPresentOperational(getDataBroker(), TOPO_IID);
376         // still, the session should not be registered and thus close() is never called
377         verify(this.listenerReg, times(0)).close();
378         // verify the session is closed due to server session manager is closed
379         assertTrue(this.session.isClosed());
380         // send request
381         final Future<RpcResult<AddLspOutput>> futureOutput = this.topologyRpcs.addLsp(createAddLspInput());
382         final AddLspOutput output = futureOutput.get().getResult();
383         // deal with unsent request after session down
384         assertEquals(FailureType.Unsent, output.getFailure());
385         // PCC client is not there
386         checkNotPresentOperational(getDataBroker(), this.pathComputationClientIId);
387
388         // reset received message queue
389         this.receivedMsgs.clear();
390         // now we restart the session manager
391         startSessionManager();
392         // try to start the session again
393         // notice since the session was terminated before, it is not usable anymore.
394         // we need to get a new session instance. the new session will have the same local / remote preference
395         this.session = getPCEPSession(getLocalPref(), getRemotePref());
396         verify(this.listenerReg, times(0)).close();
397         assertFalse(this.session.isClosed());
398         this.listener.onSessionUp(this.session);
399         assertFalse(this.session.isClosed());
400
401         // create node
402         this.topologyRpcs.addLsp(createAddLspInput());
403         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
404         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
405         final long srpId = req.getSrp().getOperationId().getValue();
406         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
407             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
408         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs).setSync(true)
409                 .setRemove(false).setOperational(OperationalStatus.Active).build(),
410             Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro().getSubobject()));
411         this.listener.onMessage(this.session, pcRpt);
412         readDataOperational(getDataBroker(), TOPO_IID, topology -> {
413             assertEquals(1, topology.getNode().size());
414             return topology;
415         });
416     }
417
418     /**
419      * When a session is somehow duplicated in controller, the controller should drop existing session
420      */
421     @Test
422     public void testDuplicatedSession() throws ReadFailedException {
423         this.listener.onSessionUp(this.session);
424         verify(this.listenerReg, times(0)).close();
425
426         // create node
427         this.topologyRpcs.addLsp(createAddLspInput());
428         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
429         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
430         final long srpId = req.getSrp().getOperationId().getValue();
431         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
432             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
433         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs).setSync(true)
434                 .setRemove(false).setOperational(OperationalStatus.Active).build(),
435             Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro().getSubobject()));
436         this.listener.onMessage(this.session, pcRpt);
437         readDataOperational(getDataBroker(), TOPO_IID, topology -> {
438             assertEquals(1, topology.getNode().size());
439             return topology;
440         });
441
442         // now we do session up again
443         this.listener.onSessionUp(this.session);
444         assertTrue(this.session.isClosed());
445         verify(this.listenerReg, times(1)).close();
446         // node should be removed after termination
447         checkNotPresentOperational(getDataBroker(), this.pathComputationClientIId);
448         assertFalse(this.receivedMsgs.isEmpty());
449         // the last message should be a Close message
450         assertTrue(this.receivedMsgs.get(this.receivedMsgs.size() - 1) instanceof Close);
451     }
452
453     @Test
454     public void testConflictingListeners() throws Exception {
455         this.listener.onSessionUp(this.session);
456         assertFalse(this.session.isClosed());
457         Stateful07TopologySessionListener conflictingListener = (Stateful07TopologySessionListener) getSessionListener();
458         conflictingListener.onSessionUp(this.session);
459         assertTrue(this.session.isClosed());
460     }
461
462     @Test
463     public void testOnSessionTermination() throws Exception {
464         this.listener.onSessionUp(this.session);
465         verify(this.listenerReg, times(0)).close();
466
467         // create node
468         this.topologyRpcs.addLsp(createAddLspInput());
469         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
470         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
471         final long srpId = req.getSrp().getOperationId().getValue();
472         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
473             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
474         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs).setSync(true)
475             .setRemove(false).setOperational(OperationalStatus.Active).build(),
476             Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro().getSubobject()));
477         this.listener.onMessage(this.session, pcRpt);
478         readDataOperational(getDataBroker(), TOPO_IID, topology -> {
479             assertEquals(1, topology.getNode().size());
480             return topology;
481         });
482
483         assertFalse(this.session.isClosed());
484         // node should be removed after termination
485         this.listener.onSessionTerminated(this.session, new PCEPCloseTermination(TerminationReason.UNKNOWN));
486         assertTrue(this.session.isClosed());
487         verify(this.listenerReg, times(1)).close();
488         checkNotPresentOperational(getDataBroker(), this.pathComputationClientIId);
489     }
490
491     @Test
492     public void testUnknownLsp() throws Exception {
493         final List<Reports> reports = Lists.newArrayList(new ReportsBuilder().setPath(new PathBuilder()
494             .setEro(new EroBuilder().build()).build()).setLsp(new LspBuilder().setPlspId(new PlspId(5L))
495             .setSync(false).setRemove(false).setTlvs(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.
496                 yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder().setLspIdentifiers(
497                     new LspIdentifiersBuilder().setLspId(new LspId(1L)).build()).setSymbolicPathName(
498                         new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(new byte[] { 22, 34 }))
499                             .build()).build()).build()).build());
500         final Pcrpt rptmsg = new PcrptBuilder().setPcrptMessage(new PcrptMessageBuilder().setReports(reports).build())
501             .build();
502         this.listener.onSessionUp(this.session);
503         this.listener.onMessage(this.session, rptmsg);
504         readDataOperational(getDataBroker(), TOPO_IID, node -> {
505             assertFalse(node.getNode().isEmpty());
506             return node;
507         });
508     }
509
510     @Test
511     public void testUpdateUnknownLsp() throws InterruptedException, ExecutionException {
512         this.listener.onSessionUp(this.session);
513         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args
514             .ArgumentsBuilder updArgsBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.
515             topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder();
516         updArgsBuilder.setEro(createEroWithIpPrefixes(Lists.newArrayList(this.eroIpPrefix, this.dstIpPrefix)));
517         updArgsBuilder.addAugmentation(Arguments3.class, new Arguments3Builder().setLsp(new LspBuilder()
518             .setDelegate(true).setAdministrative(true).build()).build());
519         final UpdateLspInput update = new UpdateLspInputBuilder().setArguments(updArgsBuilder.build())
520             .setName(this.TUNNEL_NAME).setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID)).setNode(this.nodeId)
521             .build();
522         final UpdateLspOutput result = this.topologyRpcs.updateLsp(update).get().getResult();
523         assertEquals(FailureType.Unsent, result.getFailure());
524         assertEquals(1, result.getError().size());
525         final ErrorObject errorObject = result.getError().get(0).getErrorObject();
526         assertNotNull(errorObject);
527         assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, PCEPErrors.forValue(errorObject.getType(), errorObject.getValue()));
528     }
529
530     @Test
531     public void testRemoveUnknownLsp() throws InterruptedException, ExecutionException {
532         this.listener.onSessionUp(this.session);
533         final RemoveLspInput remove = new RemoveLspInputBuilder().setName(this.TUNNEL_NAME).setNetworkTopologyRef(
534             new NetworkTopologyRef(TOPO_IID)).setNode(this.nodeId).build();
535         final OperationResult result = this.topologyRpcs.removeLsp(remove).get().getResult();
536         assertEquals(FailureType.Unsent, result.getFailure());
537         assertEquals(1, result.getError().size());
538         final ErrorObject errorObject = result.getError().get(0).getErrorObject();
539         assertNotNull(errorObject);
540         assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, PCEPErrors.forValue(errorObject.getType(), errorObject.getValue()));
541     }
542
543     @Test
544     public void testAddAlreadyExistingLsp() throws UnknownHostException, InterruptedException, ExecutionException {
545         this.listener.onSessionUp(this.session);
546         this.topologyRpcs.addLsp(createAddLspInput());
547         assertEquals(1, this.receivedMsgs.size());
548         assertTrue(this.receivedMsgs.get(0) instanceof Pcinitiate);
549         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
550         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
551         final long srpId = req.getSrp().getOperationId().getValue();
552         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
553             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
554         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs)
555             .setPlspId(new PlspId(1L)).setSync(false).setRemove(false).setOperational(OperationalStatus.Active)
556             .build(), Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro()
557             .getSubobject()));
558         this.listener.onMessage(this.session, pcRpt);
559
560         //try to add already existing LSP
561         final AddLspOutput result = this.topologyRpcs.addLsp(createAddLspInput()).get().getResult();
562         assertEquals(FailureType.Unsent, result.getFailure());
563         assertEquals(1, result.getError().size());
564         final ErrorObject errorObject = result.getError().get(0).getErrorObject();
565         assertNotNull(errorObject);
566         assertEquals(PCEPErrors.USED_SYMBOLIC_PATH_NAME, PCEPErrors.forValue(errorObject.getType(),
567             errorObject.getValue()));
568     }
569
570     @Test
571     public void testPccResponseTimeout() throws Exception {
572         this.listener.onSessionUp(this.session);
573         final Future<RpcResult<AddLspOutput>> addLspResult = this.topologyRpcs.addLsp(createAddLspInput());
574         try {
575             addLspResult.get(2, TimeUnit.SECONDS);
576             fail();
577         } catch (final Exception e) {
578             assertTrue(e instanceof TimeoutException);
579         }
580         Thread.sleep(AbstractPCEPSessionTest.RPC_TIMEOUT);
581         CheckUtil.checkEquals(()-> {
582             final RpcResult<AddLspOutput> rpcResult = addLspResult.get();
583             assertNotNull(rpcResult);
584             assertEquals(rpcResult.getResult().getFailure(), FailureType.Unsent);
585         });
586     }
587
588     @Test
589     public void testDelegatedLspsCountWithDelegation() throws Exception {
590         this.listener.onSessionUp(this.session);
591         this.topologyRpcs.addLsp(createAddLspInput());
592         assertEquals(1, this.receivedMsgs.size());
593         assertTrue(this.receivedMsgs.get(0) instanceof Pcinitiate);
594         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
595         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
596         final long srpId = req.getSrp().getOperationId().getValue();
597         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
598             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
599         //delegate set to true
600         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs)
601             .setPlspId(new PlspId(1L)).setSync(false).setRemove(false).setOperational(OperationalStatus.Active)
602             .setDelegate(true).build(), Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(
603                     req.getEro().getSubobject()));
604         this.listener.onMessage(this.session, pcRpt);
605         checkEquals(()->assertEquals(1, this.listener.getDelegatedLspsCount().intValue()));
606     }
607
608     @Test
609     public void testDelegatedLspsCountWithoutDelegation() throws Exception {
610         this.listener.onSessionUp(this.session);
611         this.topologyRpcs.addLsp(createAddLspInput());
612         assertEquals(1, this.receivedMsgs.size());
613         assertTrue(this.receivedMsgs.get(0) instanceof Pcinitiate);
614         final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
615         final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
616         final long srpId = req.getSrp().getOperationId().getValue();
617         final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
618             this.testAddress, this.testAddress, this.testAddress, Optional.absent());
619         //delegate set to false
620         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs)
621             .setPlspId(new PlspId(1L)).setSync(false).setRemove(false).setOperational(OperationalStatus.Active)
622             .setDelegate(false).build(), Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(
623                     req.getEro().getSubobject()));
624         this.listener.onMessage(this.session, pcRpt);
625         checkEquals(()->assertEquals(0, this.listener.getDelegatedLspsCount().intValue()));
626     }
627
628     @Override
629     protected Open getLocalPref() {
630         return new OpenBuilder(super.getLocalPref()).setTlvs(new TlvsBuilder().addAugmentation(Tlvs1.class,
631             new Tlvs1Builder().setStateful(new StatefulBuilder()
632             .addAugmentation(Stateful1.class, new Stateful1Builder().setInitiation(Boolean.TRUE).build())
633             .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.
634                 optimizations.rev150714.Stateful1.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.
635                 ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1Builder()
636                 .setTriggeredInitialSync(Boolean.TRUE).build())
637             .build()).build()).build()).build();
638     }
639
640     @Override
641     protected Open getRemotePref() {
642         return getLocalPref();
643     }
644
645     private AddLspInput createAddLspInput() {
646         final ArgumentsBuilder argsBuilder = new ArgumentsBuilder();
647         final Ipv4CaseBuilder ipv4Builder = new Ipv4CaseBuilder();
648         ipv4Builder.setIpv4(new Ipv4Builder().setSourceIpv4Address(new Ipv4Address(this.testAddress))
649             .setDestinationIpv4Address(new Ipv4Address(this.testAddress)).build());
650         argsBuilder.setEndpointsObj(new EndpointsObjBuilder().setAddressFamily(ipv4Builder.build()).build());
651         argsBuilder.setEro(createEroWithIpPrefixes(Lists.newArrayList(this.eroIpPrefix)));
652         argsBuilder.addAugmentation(Arguments2.class, new Arguments2Builder().setLsp(new LspBuilder()
653             .setDelegate(true).setAdministrative(true).build()).build());
654         return new AddLspInputBuilder().setName(this.TUNNEL_NAME).setArguments(argsBuilder.build())
655             .setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID)).setNode(this.nodeId).build();
656     }
657 }