482230bdb2a9b6ffdaede849652eb91f45884da2
[openflowplugin.git] / applications / lldp-speaker / src / test / java / org / opendaylight / openflowplugin / applications / lldpspeaker / LLDPSpeakerTest.java
1 /*
2  * Copyright (c) 2014 Pacnet 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.openflowplugin.applications.lldpspeaker;
10
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.anyLong;
13 import static org.mockito.Mockito.never;
14 import static org.mockito.Mockito.times;
15 import static org.mockito.Mockito.verify;
16 import static org.mockito.Mockito.verifyNoMoreInteractions;
17 import static org.mockito.Mockito.when;
18
19 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
22
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.Mock;
27 import org.mockito.runners.MockitoJUnitRunner;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.CommonPort;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.rev141023.OperStatus;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42
43 /**
44  * Tests for @{LLDPSpeaker} class.
45  */
46 @RunWith(MockitoJUnitRunner.class)
47 public class LLDPSpeakerTest {
48     static InstanceIdentifier<NodeConnector> id;
49     static FlowCapableNodeConnector fcnc;
50     static TransmitPacketInput packet;
51
52     static {
53         MacAddress mac = new MacAddress("01:23:45:67:89:AB");
54         id = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:1");
55         fcnc = TestUtils.createFlowCapableNodeConnector(mac, 1L).build();
56         byte[] lldpFrame = LLDPUtil.buildLldpFrame(new NodeId("openflow:1"),
57                 new NodeConnectorId("openflow:1:1"), mac, 1L);
58         packet = new TransmitPacketInputBuilder()
59                 .setEgress(new NodeConnectorRef(id))
60                 .setNode(new NodeRef(id.firstIdentifierOf(Node.class)))
61                 .setPayload(lldpFrame).build();
62     }
63
64     @Mock
65     PacketProcessingService packetProcessingService;
66     @Mock
67     ScheduledExecutorService scheduledExecutorService;
68     @Mock
69     ScheduledFuture scheduledSpeakerTask;
70
71     MacAddress destinationMACAddress = null;
72     LLDPSpeaker lldpSpeaker;
73
74     @Before
75     @SuppressWarnings("unchecked")
76     public void setUp() {
77         when(
78                 scheduledExecutorService.scheduleAtFixedRate(
79                         any(Runnable.class), anyLong(), anyLong(),
80                         any(TimeUnit.class))).thenReturn(scheduledSpeakerTask);
81         lldpSpeaker = new LLDPSpeaker(packetProcessingService,
82                 scheduledExecutorService, destinationMACAddress);
83         lldpSpeaker.setOperationalStatus(OperStatus.RUN);
84     }
85
86     /**
87      * Test that speaker does nothing when in {@link OperStatus.STANDBY} mode.
88      */
89     @Test
90     public void testStandBy() {
91         lldpSpeaker.setOperationalStatus(OperStatus.STANDBY);
92         // Add node connector - LLDP packet should be transmitted through
93         // packetProcessingService
94         lldpSpeaker.nodeConnectorAdded(id, fcnc);
95
96         // Execute one iteration of periodic task - LLDP packet should be
97         // transmitted second time
98         lldpSpeaker.run();
99
100         // Check packet transmission
101         verify(packetProcessingService, times(1)).transmitPacket(packet);
102         verifyNoMoreInteractions(packetProcessingService);
103     }
104
105     /**
106      * Test that LLDP frame is transmitted after port appeared in inventory and
107      * periodically after that.
108      */
109     @Test
110     public void testNodeConnectorAdd() {
111         // Add node connector - LLDP packet should be transmitted through
112         // packetProcessingService
113         lldpSpeaker.nodeConnectorAdded(id, fcnc);
114
115         // Execute one iteration of periodic task - LLDP packet should be
116         // transmitted second time
117         lldpSpeaker.run();
118
119         // Check packet transmission
120         verify(packetProcessingService, times(2)).transmitPacket(packet);
121         verifyNoMoreInteractions(packetProcessingService);
122     }
123
124     /**
125      * Test that LLDP frame stop to periodically transmit after port disappeared
126      * from inventory.
127      */
128     @Test
129     public void testNodeConnectorRemoval() {
130         // Prepare for test - add node connector first
131         lldpSpeaker.nodeConnectorAdded(id, fcnc);
132
133         // Trigger removal of packet
134         lldpSpeaker.nodeConnectorRemoved(id);
135
136         // Run one iteration of LLDP flood
137         lldpSpeaker.run();
138
139         // Verify that LLDP frame sent only once (by nodeConnectorAdded),
140         // e.g. no flood after removal
141         verify(packetProcessingService, times(1)).transmitPacket(packet);
142         verifyNoMoreInteractions(packetProcessingService);
143     }
144
145     /**
146      * Test that when @{LLDPSpeaker#nodeConnectorAdded} is called multiple times
147      * with same arguments, only the first one have effect.
148      */
149     @Test
150     public void testMultipleSameNodeConnectorAddEvents() {
151         // Add node connector - LLDP packet should be transmitted through
152         // packetProcessingService
153         for (int i = 0; i < 10; i++) {
154             lldpSpeaker.nodeConnectorAdded(id, fcnc);
155         }
156
157         // Check packet transmission
158         verify(packetProcessingService, times(1)).transmitPacket(packet);
159         verifyNoMoreInteractions(packetProcessingService);
160     }
161
162     /**
163      * Test that lldpSpeaker cancels periodic LLDP flood task and stops
164      * 
165      * @{ScheduledExecutorService .
166      * @throws Exception
167      */
168     @Test
169     public void testCleanup() throws Exception {
170         lldpSpeaker.close();
171         verify(scheduledSpeakerTask, times(1)).cancel(true);
172         verify(scheduledExecutorService, times(1)).shutdown();
173     }
174
175     /**
176      * Test that checks if LLDPSpeaker working fine with local ports.
177      */
178     @Test
179     public void testLocalNodeConnectorCreation() {
180         // Call nodeConnectorAdded with local port
181         FlowCapableNodeConnector fcnc = TestUtils
182                 .createFlowCapableNodeConnector()
183                 .setPortNumber(new CommonPort.PortNumber("LOCAL")).build();
184         lldpSpeaker.nodeConnectorAdded(id, fcnc);
185
186         // Verify that nothing happened for local port
187         verify(packetProcessingService, never()).transmitPacket(
188                 any(TransmitPacketInput.class));
189     }
190 }