BUG-197: improve session ID tracking
[bgpcep.git] / pcep / impl / src / test / java / org / opendaylight / protocol / pcep / impl / FiniteStateMachineTest.java
1 /*
2  * Copyright (c) 2013 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 package org.opendaylight.protocol.pcep.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import io.netty.channel.Channel;
17 import io.netty.channel.ChannelFuture;
18 import io.netty.channel.ChannelHandler;
19 import io.netty.channel.ChannelPipeline;
20 import io.netty.channel.DefaultChannelPromise;
21 import io.netty.util.HashedWheelTimer;
22 import io.netty.util.concurrent.DefaultPromise;
23 import io.netty.util.concurrent.GlobalEventExecutor;
24
25 import java.net.SocketAddress;
26 import java.util.Arrays;
27 import java.util.List;
28
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.mockito.Mock;
34 import org.mockito.MockitoAnnotations;
35 import org.mockito.invocation.InvocationOnMock;
36 import org.mockito.stubbing.Answer;
37 import org.opendaylight.protocol.pcep.spi.PCEPErrorMapping;
38 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Keepalive;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.KeepaliveBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Open;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.OpenBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.OpenMessage;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.keepalive.message.KeepaliveMessageBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.message.OpenMessageBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.Errors;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.error.type.SessionCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.error.type.session._case.SessionBuilder;
54 import org.opendaylight.yangtools.yang.binding.Notification;
55
56 import com.google.common.collect.Lists;
57
58 public class FiniteStateMachineTest {
59
60         private DefaultPCEPSessionNegotiator serverSession;
61
62         @Mock
63         private Channel clientListener;
64
65         @Mock
66         private ChannelPipeline pipeline;
67
68         @Mock
69         private SocketAddress address;
70
71         private final List<Notification> receivedMsgs = Lists.newArrayList();
72
73         private Open openmsg;
74
75         private Keepalive kamsg;
76
77         @Before
78         public void setUp() {
79                 MockitoAnnotations.initMocks(this);
80                 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open localPrefs = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder().setKeepalive(
81                                 (short) 1).build();
82                 this.serverSession = new DefaultPCEPSessionNegotiator(new HashedWheelTimer(), new DefaultPromise<PCEPSessionImpl>(GlobalEventExecutor.INSTANCE), this.clientListener, new SimpleSessionListener(), (short) 1, 20, localPrefs);
83                 final ChannelFuture future = new DefaultChannelPromise(this.clientListener);
84                 doAnswer(new Answer<Object>() {
85                         @Override
86                         public Object answer(final InvocationOnMock invocation) {
87                                 final Object[] args = invocation.getArguments();
88                                 FiniteStateMachineTest.this.receivedMsgs.add((Notification) args[0]);
89                                 return future;
90                         }
91                 }).when(this.clientListener).writeAndFlush(any(Notification.class));
92                 doReturn("TestingChannel").when(this.clientListener).toString();
93                 doReturn(this.pipeline).when(this.clientListener).pipeline();
94                 doReturn(this.address).when(this.clientListener).localAddress();
95                 doReturn(this.address).when(this.clientListener).remoteAddress();
96                 doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
97                 doReturn(true).when(this.clientListener).isActive();
98                 doReturn(mock(ChannelFuture.class)).when(this.clientListener).close();
99                 this.openmsg = new OpenBuilder().setOpenMessage(
100                                 new OpenMessageBuilder().setOpen(
101                                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder().setDeadTimer(
102                                                                 (short) 45).setKeepalive((short) 15).build()).build()).build();
103                 this.kamsg = new KeepaliveBuilder().setKeepaliveMessage(new KeepaliveMessageBuilder().build()).build();
104         }
105
106         /**
107          * Both PCEs accept session characteristics. Also tests KeepAliveTimer and error message and when pce attempts to
108          * establish pce session for the 2nd time.
109          * 
110          * @throws Exception
111          */
112         @Test
113         public void testSessionCharsAccBoth() throws Exception {
114                 this.serverSession.channelActive(null);
115                 assertEquals(1, this.receivedMsgs.size());
116                 assertTrue(this.receivedMsgs.get(0) instanceof Open);
117                 this.serverSession.handleMessage(this.openmsg);
118                 assertEquals(2, this.receivedMsgs.size());
119                 assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
120                 this.serverSession.handleMessage(this.kamsg);
121                 assertEquals(this.serverSession.getState(), DefaultPCEPSessionNegotiator.State.Finished);
122         }
123
124         /**
125          * Mock PCE does not accept session characteristics the first time.
126          * 
127          * @throws Exception
128          */
129         @Test
130         public void testSessionCharsAccMe() throws Exception {
131                 this.serverSession.channelActive(null);
132                 assertEquals(1, this.receivedMsgs.size());
133                 assertTrue(this.receivedMsgs.get(0) instanceof Open);
134                 this.serverSession.handleMessage(this.openmsg);
135                 assertEquals(2, this.receivedMsgs.size());
136                 assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
137                 this.serverSession.handleMessage(createErrorMessageWOpen(PCEPErrors.NON_ACC_NEG_SESSION_CHAR));
138                 assertEquals(3, this.receivedMsgs.size());
139                 assertTrue(this.receivedMsgs.get(2) instanceof Open);
140                 this.serverSession.handleMessage(this.kamsg);
141                 assertEquals(this.serverSession.getState(), DefaultPCEPSessionNegotiator.State.Finished);
142         }
143
144         private Pcerr createErrorMessageWOpen(final PCEPErrors e) {
145                 final PCEPErrorMapping maping = PCEPErrorMapping.getInstance();
146                 return new PcerrBuilder().setPcerrMessage(
147                                 new PcerrMessageBuilder().setErrorType(
148                                                 new SessionCaseBuilder().setSession(
149                                                                 new SessionBuilder().setOpen(
150                                                                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder().setKeepalive(
151                                                                                                 (short) 1).build()).build()).build()).setErrors(
152                                                                                                                 Arrays.asList(new ErrorsBuilder().setErrorObject(
153                                                                                                                                 new ErrorObjectBuilder().setType(maping.getFromErrorsEnum(e).type).setValue(
154                                                                                                                                                 maping.getFromErrorsEnum(e).value).build()).build())).build()).build();
155         }
156
157         /**
158          * Sending different PCEP Message than Open in session establishment phase.
159          * 
160          * @throws Exception
161          */
162         @Test
163         public void testErrorOneOne() throws Exception {
164                 this.serverSession.channelActive(null);
165                 assertEquals(1, this.receivedMsgs.size());
166                 assertTrue(this.receivedMsgs.get(0) instanceof Open);
167                 this.serverSession.handleMessage(this.kamsg);
168                 for (final Notification m : this.receivedMsgs) {
169                         if (m instanceof Pcerr) {
170                                 final Errors obj = ((Pcerr) m).getPcerrMessage().getErrors().get(0);
171                                 assertEquals(new Short((short) 1), obj.getErrorObject().getType());
172                                 assertEquals(new Short((short) 1), obj.getErrorObject().getValue());
173                         }
174                 }
175         }
176
177         /**
178          * KeepWaitTimer expired.
179          * 
180          * @throws Exception
181          */
182         @Test
183         public void testErrorOneSeven() throws Exception {
184                 this.serverSession.channelActive(null);
185                 assertEquals(1, this.receivedMsgs.size());
186                 assertTrue(this.receivedMsgs.get(0) instanceof Open);
187                 this.serverSession.handleMessage(this.openmsg);
188                 Thread.sleep(1000);
189                 for (final Notification m : this.receivedMsgs) {
190                         if (m instanceof Pcerr) {
191                                 final Errors obj = ((Pcerr) m).getPcerrMessage().getErrors().get(0);
192                                 assertEquals(new Short((short) 1), obj.getErrorObject().getType());
193                                 assertEquals(new Short((short) 7), obj.getErrorObject().getValue());
194                         }
195                 }
196         }
197
198         /************* Tests commented because of their long duration (tested timers) **************/
199
200         /**
201          * OpenWait timer expired.
202          * 
203          * @throws InterruptedException
204          */
205         @Test
206         @Ignore
207         public void testErrorOneTwo() throws InterruptedException {
208                 this.serverSession.channelActive(null);
209                 assertEquals(1, this.receivedMsgs.size());
210                 assertTrue(this.receivedMsgs.get(0) instanceof OpenMessage);
211                 Thread.sleep(60 * 1000);
212                 for (final Notification m : this.receivedMsgs) {
213                         if (m instanceof Pcerr) {
214                                 final Errors obj = ((Pcerr) m).getPcerrMessage().getErrors().get(0);
215                                 assertEquals(new Short((short) 1), obj.getErrorObject().getType());
216                                 assertEquals(new Short((short) 2), obj.getErrorObject().getValue());
217                         }
218                 }
219         }
220
221         @Test
222         @Ignore
223         public void testUnknownMessage() throws InterruptedException {
224                 final SimpleSessionListener client = new SimpleSessionListener();
225                 final PCEPSessionImpl s = new PCEPSessionImpl(new HashedWheelTimer(), client, 5, this.clientListener, this.openmsg.getOpenMessage().getOpen(), this.openmsg.getOpenMessage().getOpen());
226                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
227                 assertEquals(1, s.unknownMessagesTimes.size());
228                 Thread.sleep(10000);
229                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
230                 assertEquals(2, s.unknownMessagesTimes.size());
231                 Thread.sleep(10000);
232                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
233                 assertEquals(3, s.unknownMessagesTimes.size());
234                 Thread.sleep(20000);
235                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
236                 assertEquals(4, s.unknownMessagesTimes.size());
237                 Thread.sleep(30000);
238                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
239                 assertEquals(3, s.unknownMessagesTimes.size());
240                 Thread.sleep(10000);
241                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
242                 assertEquals(3, s.unknownMessagesTimes.size());
243                 Thread.sleep(5000);
244                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
245                 assertEquals(4, s.unknownMessagesTimes.size());
246                 Thread.sleep(1000);
247                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
248                 assertEquals(5, s.unknownMessagesTimes.size());
249                 Thread.sleep(1000);
250                 s.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
251                 synchronized (client) {
252                         while (client.up) {
253                                 try {
254                                         client.wait();
255                                 } catch (final InterruptedException e) {
256                                         e.printStackTrace();
257                                 }
258                         }
259                 }
260                 assertTrue(!client.up);
261         }
262
263         @After
264         public void tearDown() {
265         }
266 }