2 * Copyright (c) 2014 Pacnet and others. All rights reserved.
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
9 package org.opendaylight.openflowplugin.applications.lldpspeaker;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.ArgumentMatchers.anyLong;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.never;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.verifyNoMoreInteractions;
18 import static org.mockito.Mockito.when;
20 import java.security.NoSuchAlgorithmException;
21 import java.util.concurrent.ScheduledExecutorService;
22 import java.util.concurrent.ScheduledFuture;
23 import java.util.concurrent.TimeUnit;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.mockito.Mock;
28 import org.mockito.runners.MockitoJUnitRunner;
29 import org.opendaylight.openflowplugin.applications.deviceownershipservice.DeviceOwnershipService;
30 import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.rev141023.OperStatus;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 * Tests for {@link LLDPSpeaker}.
50 @RunWith(MockitoJUnitRunner.class)
51 public class LLDPSpeakerTest {
52 private static final InstanceIdentifier<NodeConnector> ID = TestUtils.createNodeConnectorId("openflow:1",
54 private static final MacAddress MAC_ADDRESS = new MacAddress("01:23:45:67:89:AB");
55 private static final FlowCapableNodeConnector FLOW_CAPABLE_NODE_CONNECTOR =
56 TestUtils.createFlowCapableNodeConnector(MAC_ADDRESS, 1L).build();
57 private TransmitPacketInput packetInput;
60 private PacketProcessingService packetProcessingService;
62 private ScheduledExecutorService scheduledExecutorService;
64 private ScheduledFuture scheduledSpeakerTask;
66 private DeviceOwnershipService deviceOwnershipService;
68 private LLDPSpeaker lldpSpeaker;
71 public void setUp() throws NoSuchAlgorithmException, PacketException {
72 byte[] lldpFrame = LLDPUtil.buildLldpFrame(new NodeId("openflow:1"),
73 new NodeConnectorId("openflow:1:1"), MAC_ADDRESS, 1L);
74 packetInput = new TransmitPacketInputBuilder().setEgress(new NodeConnectorRef(ID))
75 .setNode(new NodeRef(ID.firstIdentifierOf(Node.class))).setPayload(lldpFrame).build();
77 when(scheduledExecutorService.scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(),
78 any(TimeUnit.class))).thenReturn(scheduledSpeakerTask);
79 lldpSpeaker = new LLDPSpeaker(packetProcessingService,
80 scheduledExecutorService, null, deviceOwnershipService);
81 when(deviceOwnershipService.isEntityOwned(any())).thenReturn(true);
82 lldpSpeaker.setOperationalStatus(OperStatus.RUN);
84 doReturn(RpcResultBuilder.success().buildFuture()).when(packetProcessingService).transmitPacket(any());
88 * Test that speaker does nothing when in {@link OperStatus.STANDBY} mode.
91 public void testStandBy() {
92 lldpSpeaker.setOperationalStatus(OperStatus.STANDBY);
93 // Add node connector - LLDP packet should be transmitted through
94 // packetProcessingService
95 lldpSpeaker.nodeConnectorAdded(ID, FLOW_CAPABLE_NODE_CONNECTOR);
97 // Execute one iteration of periodic task - LLDP packet should be
98 // transmitted second time
101 // Check packet transmission
102 verify(packetProcessingService, times(1)).transmitPacket(packetInput);
103 verifyNoMoreInteractions(packetProcessingService);
107 * Test that LLDP frame is transmitted after port appeared in inventory and
108 * periodically after that.
111 public void testNodeConnectorAdd() {
112 // Add node connector - LLDP packet should be transmitted through
113 // packetProcessingService
114 lldpSpeaker.nodeConnectorAdded(ID, FLOW_CAPABLE_NODE_CONNECTOR);
117 when(deviceOwnershipService.isEntityOwned(any())).thenReturn(false);
118 // Execute one iteration of periodic task - LLDP packet should be
119 // not transmit second packet because it doesn't own the device.
122 // Check packet transmission
123 verify(packetProcessingService, times(1)).transmitPacket(packetInput);
124 verifyNoMoreInteractions(packetProcessingService);
128 * Test that LLDP frame stop to periodically transmit after port disappeared
132 public void testNodeConnectorRemoval() {
133 // Prepare for test - add node connector first
134 lldpSpeaker.nodeConnectorAdded(ID, FLOW_CAPABLE_NODE_CONNECTOR);
136 // Trigger removal of packet
137 lldpSpeaker.nodeConnectorRemoved(ID);
139 // Run one iteration of LLDP flood
142 // Verify that LLDP frame sent only once (by nodeConnectorAdded),
143 // e.g. no flood after removal
144 verify(packetProcessingService, times(1)).transmitPacket(packetInput);
145 verifyNoMoreInteractions(packetProcessingService);
149 * Test that when {@link LLDPSpeaker#nodeConnectorAdded} is called multiple times
150 * with same arguments, only the first one have effect.
153 public void testMultipleSameNodeConnectorAddEvents() {
154 // Add node connector - LLDP packet should be transmitted through
155 // packetProcessingService
156 for (int i = 0; i < 10; i++) {
157 lldpSpeaker.nodeConnectorAdded(ID, FLOW_CAPABLE_NODE_CONNECTOR);
160 // Check packet transmission
161 verify(packetProcessingService, times(1)).transmitPacket(packetInput);
162 verifyNoMoreInteractions(packetProcessingService);
166 * Test that checks if LLDPSpeaker working fine with local ports.
169 public void testLocalNodeConnectorCreation() {
170 // Call nodeConnectorAdded with local port
171 FlowCapableNodeConnector fcnc = TestUtils
172 .createFlowCapableNodeConnector()
173 .setPortNumber(new PortNumberUni("LOCAL")).build();
174 lldpSpeaker.nodeConnectorAdded(ID, fcnc);
176 // Verify that nothing happened for local port
177 verify(packetProcessingService, never()).transmitPacket(
178 any(TransmitPacketInput.class));