External api proposal
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / HandshakeManagerImplTest.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.openflowplugin.openflow.md.core;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.junit.After;
14 import org.junit.Assert;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 import org.mockito.ArgumentCaptor;
19 import org.mockito.Matchers;
20 import org.mockito.Mock;
21 import org.mockito.Mockito;
22 import org.mockito.runners.MockitoJUnitRunner;
23 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
24 import org.opendaylight.openflowplugin.api.OFConstants;
25 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
26 import org.opendaylight.openflowplugin.api.openflow.md.core.ErrorHandler;
27 import org.opendaylight.openflowplugin.api.openflow.md.core.HandshakeListener;
28 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
37 import org.opendaylight.yangtools.yang.common.RpcResult;
38 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import com.google.common.collect.Lists;
43 import com.google.common.util.concurrent.Futures;
44
45 /**
46  * testing handshake
47  */
48 @RunWith(MockitoJUnitRunner.class)
49 public class HandshakeManagerImplTest {
50
51     private static final Logger LOG = LoggerFactory
52             .getLogger(HandshakeManagerImplTest.class);
53
54     private HandshakeManagerImpl handshakeManager;
55     @Mock
56     private ConnectionAdapter adapter;
57     @Mock
58     private ErrorHandler errorHandler;
59     @Mock
60     private HandshakeListener handshakeListener;
61
62     private RpcResult<GetFeaturesOutput> resultFeatures;
63
64     private long helloXid = 42L;
65
66     private int expectedErrors = 0;
67
68     /**
69      * invoked before every test method
70      */
71     @Before
72     public void setUp() {
73         handshakeManager = new HandshakeManagerImpl(adapter, OFConstants.OFP_VERSION_1_3, 
74                 ConnectionConductor.versionOrder);
75         handshakeManager.setErrorHandler(errorHandler);
76         handshakeManager.setHandshakeListener(handshakeListener);
77         handshakeManager.setUseVersionBitmap(false);
78
79         resultFeatures = RpcResultBuilder.success(new GetFeaturesOutputBuilder().build()).build();
80
81         Mockito.when(adapter.hello(Matchers.any(HelloInput.class)))
82             .thenReturn(Futures.immediateFuture(
83                     RpcResultBuilder.success((Void) null).build()));
84     }
85
86     /**
87      * invoked after each test method
88      */
89     @After
90     public void teardown() {
91         // logging errors if occurred
92         ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
93         Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
94                 errorCaptor.capture(), Matchers.any(SessionContext.class));
95         for (Throwable problem : errorCaptor.getAllValues()) {
96             LOG.warn(problem.getMessage(), problem);
97         }
98
99         Mockito.verify(errorHandler, Mockito.times(expectedErrors)).handleException(
100                 Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
101     }
102
103     /**
104      * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl#proposeCommonBitmapVersion(java.util.List)}.
105      */
106     @Test
107     public void testProposeCommonBitmapVersion() {
108         Boolean[][] versions = new Boolean[][] {
109                 {true, true, true, false, false, false},
110                 {true, true, true, false, false}
111         };
112
113         for (Boolean[] verasionList : versions) {
114             ElementsBuilder elementsBuilder = new ElementsBuilder();
115             elementsBuilder.setVersionBitmap(Lists.newArrayList(verasionList));
116             Elements element = elementsBuilder.build();
117             List<Elements> elements = Lists.newArrayList(element );
118             Short proposal = handshakeManager.proposeCommonBitmapVersion(elements);
119             Assert.assertEquals(Short.valueOf((short)1), proposal);
120         }
121     }
122
123     /**
124      * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl#proposeNextVersion(short)}.
125      */
126     @Test
127     public void testProposeNextVersion() {
128         short[] remoteVer = new short[] { 0x05, 0x04, 0x03, 0x02, 0x01, 0x8f,
129                 0xff };
130         short[] expectedProposal = new short[] { 0x04, 0x04, 0x01, 0x01, 0x01,
131                 0x04, 0x04 };
132
133         for (int i = 0; i < remoteVer.length; i++) {
134             short actualProposal = handshakeManager
135                     .proposeNextVersion(remoteVer[i]);
136             Assert.assertEquals(
137                     String.format("proposing for version: %04x", remoteVer[i]),
138                     expectedProposal[i], actualProposal);
139         }
140
141         try {
142             handshakeManager.proposeNextVersion((short) 0);
143             Assert.fail("there should be no proposition for this version");
144         } catch (Exception e) {
145             // expected
146         }
147     }
148
149     //////// Version Negotiation Tests //////////////
150
151     /**
152      * Test of version negotiation Where switch version = 1.0
153      *
154      * @throws Exception
155      */
156     @Test
157     public void testVersionNegotiation10() throws Exception {
158         LOG.debug("testVersionNegotiation10");
159         Short version = OFConstants.OFP_VERSION_1_0;
160
161         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
162             .thenReturn(Futures.immediateFuture(resultFeatures));
163
164         handshakeManager.shake();
165
166         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
167         handshakeManager.shake();
168
169         Mockito.verify(handshakeListener).onHandshakeSuccessfull(resultFeatures.getResult(), version);
170     }
171
172     /**
173      * Test of version negotiation Where switch version = 1.0
174      *
175      * @throws Exception
176      */
177     @Test
178     public void testVersionNegotiation10SwitchStarts() throws Exception {
179         LOG.debug("testVersionNegotiation10-ss");
180         Short version = OFConstants.OFP_VERSION_1_0;
181
182         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
183             .thenReturn(Futures.immediateFuture(resultFeatures));
184
185         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
186         handshakeManager.shake();
187
188         Mockito.verify(handshakeListener).onHandshakeSuccessfull(resultFeatures.getResult(), version);
189     }
190
191     /**
192      * Test of version negotiation Where switch version < 1.0
193      * Switch delivers first helloMessage with version 0x00 = negotiation unsuccessful 
194      * @throws Exception
195      */
196     @Test
197     public void testVersionNegotiation00() throws Exception {
198         LOG.debug("testVersionNegotiation00");
199         expectedErrors = 1;
200         Short version = (short) 0x00;
201
202         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
203         handshakeManager.shake();
204
205         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
206                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
207     }
208
209     /**
210      * Test of version negotiation Where switch version < 1.0
211      * Switch delivers first helloMessage with version 0x00 = negotiation unsuccessful 
212      * @throws Exception
213      */
214     @Test
215     public void testVersionNegotiation00SwitchStarts() throws Exception {
216         LOG.debug("testVersionNegotiation00-ss");
217         expectedErrors = 1;
218         Short version = (short) 0x00;
219
220         handshakeManager.shake();
221
222         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
223         handshakeManager.shake();
224
225         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
226                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
227     }
228
229     /**
230      * Test of version negotiation Where 1.0 < switch version < 1.3
231      *
232      * @throws Exception
233      */
234     @Test
235     public void testVersionNegotiation11() throws Exception {
236         LOG.debug("testVersionNegotiation11");
237         Short version = (short) 0x02;
238         Short expVersion = (short) 0x01;
239
240         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
241             .thenReturn(Futures.immediateFuture(resultFeatures));
242
243         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
244         handshakeManager.shake();
245
246         handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
247         handshakeManager.shake();
248
249         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
250                 resultFeatures.getResult(), expVersion);
251     }
252
253     /**
254      * Test of version negotiation Where 1.0 < switch version < 1.3
255      *
256      * @throws Exception
257      */
258     @Test
259     public void testVersionNegotiation11SwitchStarts() throws Exception {
260         LOG.debug("testVersionNegotiation11-ss");
261         Short version = (short) 0x02;
262         Short expVersion = (short) 0x01;
263
264         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
265             .thenReturn(Futures.immediateFuture(resultFeatures));
266
267         handshakeManager.shake();
268
269         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
270         handshakeManager.shake();
271
272         handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
273         handshakeManager.shake();
274
275         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
276                 resultFeatures.getResult(), expVersion);
277     }
278
279     /**
280      * Test of version negotiation Where switch version = 1.3
281      *
282      * @throws Exception
283      */
284     @Test
285     public void testVersionNegotiation13() throws Exception {
286         LOG.debug("testVersionNegotiation13");
287         Short version = OFConstants.OFP_VERSION_1_3;
288
289         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
290             .thenReturn(Futures.immediateFuture(resultFeatures));
291
292         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
293         handshakeManager.shake();
294
295         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
296                 resultFeatures.getResult(), version);
297     }
298
299     /**
300      * Test of version negotiation Where switch version = 1.3
301      *
302      * @throws Exception
303      */
304     @Test
305     public void testVersionNegotiation13SwitchStarts() throws Exception {
306         LOG.debug("testVersionNegotiation13-ss");
307         Short version = OFConstants.OFP_VERSION_1_3;
308
309         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
310             .thenReturn(Futures.immediateFuture(resultFeatures));
311
312         handshakeManager.shake();
313
314         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
315         handshakeManager.shake();
316
317         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
318                 resultFeatures.getResult(), version);
319     }
320
321     /**
322      * Test of version negotiation Where switch version >= 1.3
323      *
324      * @throws Exception
325      */
326     @Test
327     public void testVersionNegotiation15() throws Exception {
328         LOG.debug("testVersionNegotiation15");
329         Short version = (short) 0x06;
330         Short expVersion =  OFConstants.OFP_VERSION_1_3;
331
332         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
333             .thenReturn(Futures.immediateFuture(resultFeatures));
334
335         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
336         handshakeManager.shake();
337
338         handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
339         handshakeManager.shake();
340
341         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
342                 resultFeatures.getResult(), expVersion);
343     }
344
345     /**
346      * Test of version negotiation Where switch version >= 1.3
347      *
348      * @throws Exception
349      */
350     @Test
351     public void testVersionNegotiation15SwitchStart() throws Exception {
352         LOG.debug("testVersionNegotiation15-ss");
353         Short version = (short) 0x06;
354         Short expVersion =  OFConstants.OFP_VERSION_1_3;
355
356         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
357             .thenReturn(Futures.immediateFuture(resultFeatures));
358
359         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
360         handshakeManager.shake();
361
362         handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
363         handshakeManager.shake();
364
365         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
366                 resultFeatures.getResult(), expVersion);
367     }
368
369     /**
370      * Test of version negotiation Where switch version > 1.3
371      *
372      * @throws Exception
373      */
374     @Test
375     public void testVersionNegotiation15_MultipleCall() throws Exception {
376         LOG.debug("testVersionNegotiation15_MultipleCall");
377         Short version = (short) 0x06;
378         expectedErrors = 1;
379
380         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
381         handshakeManager.shake();
382
383         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
384         handshakeManager.shake();
385
386         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
387                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
388     }
389
390     /**
391      * Test of version negotiation Where switch version > 1.3
392      *
393      * @throws Exception
394      */
395     @Test
396     public void testVersionNegotiation15_MultipleCallSwitchStarts() throws Exception {
397         LOG.debug("testVersionNegotiation15_MultipleCall-ss");
398         Short version = (short) 0x06;
399         expectedErrors = 1;
400
401         handshakeManager.shake();
402
403         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
404         handshakeManager.shake();
405
406         handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
407         handshakeManager.shake();
408
409         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
410                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
411     }
412
413     /**
414      * Test of version negotiation Where bitmap version {0x05,0x01}
415      *
416      * @throws Exception
417      */
418     @Test
419     public void testVersionNegotiation10InBitmap() throws Exception {
420         LOG.debug("testVersionNegotiation10InBitmap");
421         Short version = OFConstants.OFP_VERSION_1_0;
422         handshakeManager.setUseVersionBitmap(true);
423
424         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
425         addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
426
427         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
428             .thenReturn(Futures.immediateFuture(resultFeatures));
429
430         handshakeManager.setReceivedHello(helloMessage.build());
431         handshakeManager.shake();
432
433         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
434                 resultFeatures.getResult(), version);
435     }
436
437     /**
438      * Test of version negotiation Where bitmap version {0x05,0x01}
439      *
440      * @throws Exception
441      */
442     @Test
443     public void testVersionNegotiation10InBitmapSwitchStarts() throws Exception {
444         LOG.debug("testVersionNegotiation10InBitmap-ss");
445         Short version = OFConstants.OFP_VERSION_1_0;
446         handshakeManager.setUseVersionBitmap(true);
447
448         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
449         addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
450
451         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
452             .thenReturn(Futures.immediateFuture(resultFeatures));
453
454         handshakeManager.shake();
455
456         handshakeManager.setReceivedHello(helloMessage.build());
457         handshakeManager.shake();
458
459         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
460                 resultFeatures.getResult(), version);
461     }
462
463     /**
464      * Test of version negotiation Where bitmap version {0x05,0x04}
465      *
466      * @throws Exception
467      */
468     @Test
469     public void testVersionNegotiation13InBitmap() throws Exception {
470         LOG.debug("testVersionNegotiation13InBitmap");
471         Short version = OFConstants.OFP_VERSION_1_3;
472         handshakeManager.setUseVersionBitmap(true);
473
474         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
475         addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
476
477         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
478             .thenReturn(Futures.immediateFuture(resultFeatures));
479
480         handshakeManager.setReceivedHello(helloMessage.build());
481         handshakeManager.shake();
482
483         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
484                 resultFeatures.getResult(), version);
485     }
486
487     /**
488      * Test of version negotiation Where bitmap version {0x05,0x04}
489      *
490      * @throws Exception
491      */
492     @Test
493     public void testVersionNegotiation13InBitmapSwitchFirst() throws Exception {
494         LOG.debug("testVersionNegotiation13InBitmap-ss");
495         Short version = OFConstants.OFP_VERSION_1_3;
496         handshakeManager.setUseVersionBitmap(true);
497
498         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
499         addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
500
501         Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
502             .thenReturn(Futures.immediateFuture(resultFeatures));
503
504         handshakeManager.shake();
505
506         handshakeManager.setReceivedHello(helloMessage.build());
507         handshakeManager.shake();
508
509         Mockito.verify(handshakeListener).onHandshakeSuccessfull(
510                 resultFeatures.getResult(), version);
511     }
512
513     /**
514      * Test of version negotiation Where bitmap version {0x05,0x02}
515      *
516      * @throws Exception
517      */
518     @Test
519     public void testVersionNegotiationNoCommonVersionInBitmap() throws Exception {
520         LOG.debug("testVersionNegotiationNoCommonVersionInBitmap");
521         Short version = (short) 0x05;
522         expectedErrors = 1;
523         handshakeManager.setUseVersionBitmap(true);
524
525         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
526         addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
527
528         handshakeManager.setReceivedHello(helloMessage.build());
529         handshakeManager.shake();
530
531         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
532                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
533     }
534
535     /**
536      * Test of version negotiation Where bitmap version {0x05,0x02}
537      *
538      * @throws Exception
539      */
540     @Test
541     public void testVersionNegotiationNoCommonVersionInBitmapSwitchStarts() throws Exception {
542         LOG.debug("testVersionNegotiationNoCommonVersionInBitmap-ss");
543         Short version = (short) 0x05;
544         expectedErrors = 1;
545         handshakeManager.setUseVersionBitmap(true);
546
547         HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
548         addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
549
550         handshakeManager.shake();
551
552         handshakeManager.setReceivedHello(helloMessage.build());
553         handshakeManager.shake();
554
555         Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
556                 Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
557     }
558
559
560     /**
561      * @param ofpVersion10
562      * @param helloXid
563      * @return
564      */
565     private static HelloMessageBuilder createHelloMessage(short ofpVersion10, long helloXid) {
566         return new HelloMessageBuilder().setVersion(ofpVersion10).setXid(helloXid);
567     }
568
569     /**
570      * @param versionOrder
571      * @param helloBuilder
572      * @return
573      */
574     private static HelloMessageBuilder addVersionBitmap(List<Short> versionOrder, 
575             HelloMessageBuilder helloBuilder) {
576         short highestVersion = versionOrder.get(0);
577         int elementsCount = highestVersion / Integer.SIZE;
578         ElementsBuilder elementsBuilder = new ElementsBuilder();
579
580         List<Elements> elementList = new ArrayList<>();
581         int orderIndex = versionOrder.size();
582         int value = versionOrder.get(--orderIndex);
583         for (int index = 0; index <= elementsCount; index++) {
584             List<Boolean> booleanList = new ArrayList<>();
585             for (int i = 0; i < Integer.SIZE; i++) {
586                 if (value == ((index * Integer.SIZE) + i)) {
587                     booleanList.add(true);
588                     value = (orderIndex == 0) ? highestVersion : versionOrder.get(--orderIndex);
589                 } else {
590                     booleanList.add(false);
591                 }
592             }
593             elementsBuilder.setType(HelloElementType.forValue(1));
594             elementsBuilder.setVersionBitmap(booleanList);
595             elementList.add(elementsBuilder.build());
596         }
597
598         helloBuilder.setElements(elementList);
599         return helloBuilder;
600     }
601
602 }