BUG 3548 - LLDP speaker doesn't start send LLDP packet on port up.
[openflowplugin.git] / applications / lldp-speaker / src / test / java / org / opendaylight / openflowplugin / applications / lldpspeaker / NodeConnectorInventoryEventTranslatorTest.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.Mockito.*;
12
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Map;
16 import java.util.Set;
17 import org.junit.*;
18 import org.junit.runner.RunWith;
19 import org.mockito.Mock;
20 import org.mockito.runners.MockitoJUnitRunner;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31
32
33 /**
34  * Tests for @{NodeConnectorInventoryEventTranslator} class.
35  */
36 @RunWith(MockitoJUnitRunner.class)
37 public class NodeConnectorInventoryEventTranslatorTest {
38     static InstanceIdentifier<NodeConnector> id = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:1");
39     static InstanceIdentifier<FlowCapableNodeConnector> iiToConnector = id.augmentation(FlowCapableNodeConnector.class);
40     static FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector().build();
41
42     @Mock DataBroker dataBroker;
43     @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
44     @Mock NodeConnectorEventsObserver eventsObserver;
45     @Mock NodeConnectorEventsObserver eventsObserver2;
46
47     MockDataChangedEvent dataChangedEvent = new MockDataChangedEvent();
48     NodeConnectorInventoryEventTranslator translator;
49
50     @Before
51     public void setUp() {
52
53         when(dataBroker.registerDataChangeListener(
54                 any(LogicalDatastoreType.class),
55                 any(InstanceIdentifier.class),
56                 any(DataChangeListener.class),
57                 any(AsyncDataBroker.DataChangeScope.class)))
58                 .thenReturn(dataChangeListenerRegistration);
59         translator = new NodeConnectorInventoryEventTranslator(dataBroker, eventsObserver, eventsObserver2);
60     }
61
62     /**
63      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorAdded} is called
64      * for each FlowCapableNodeConnector item that @{AsyncDataChangeEvent#getCreatedData} return.
65      */
66     @Test
67     public void testNodeConnectorCreation() {
68         // Setup dataChangedEvent to mock new port creation in inventory
69         dataChangedEvent.created.put(iiToConnector, fcnc);
70
71         // Invoke NodeConnectorInventoryEventTranslator and check result
72         translator.onDataChanged(dataChangedEvent);
73         verify(eventsObserver).nodeConnectorAdded(id, fcnc);
74     }
75
76     /**
77      * Test that checks that nothing is called when port appeared in inventory in link down state.
78      */
79     @Test
80     public void testNodeConnectorCreationLinkDown() {
81         FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(true, false).build();
82
83         // Setup dataChangedEvent to mock new port creation in inventory
84         dataChangedEvent.created.put(id, fcnc);
85
86         // Invoke NodeConnectorInventoryEventTranslator and check result
87         translator.onDataChanged(dataChangedEvent);
88         verifyZeroInteractions(eventsObserver);
89     }
90
91     /**
92      * Test that checks that nothing is called when port appeared in inventory in admin down state.
93      */
94     @Test
95     public void testNodeConnectorCreationAdminDown() {
96         FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(false, true).build();
97
98         // Setup dataChangedEvent to mock new port creation in inventory
99         dataChangedEvent.created.put(id, fcnc);
100
101         // Invoke NodeConnectorInventoryEventTranslator and check result
102         translator.onDataChanged(dataChangedEvent);
103         verifyZeroInteractions(eventsObserver);
104     }
105
106     /**
107      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorRemoved} is called
108      * for each FlowCapableNodeConnector item inside @{AsyncDataChangeEvent#getUpdatedData}
109      * that have link down state.
110      */
111     @Test
112     public void testNodeConnectorUpdateToLinkDown() {
113         FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(true, false).build();
114
115         // Setup dataChangedEvent to mock link down
116         dataChangedEvent.updated.put(iiToConnector, fcnc);
117
118         // Invoke NodeConnectorInventoryEventTranslator and check result
119         translator.onDataChanged(dataChangedEvent);
120         verify(eventsObserver).nodeConnectorRemoved(id);
121     }
122
123     /**
124      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorRemoved} is called
125      * for each FlowCapableNodeConnector item inside @{AsyncDataChangeEvent#getUpdatedData}
126      * that have administrative down state.
127      */
128     @Test
129     public void testNodeConnectorUpdateToAdminDown() {
130         FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(false, true).build();
131
132         // Setup dataChangedEvent to mock link down and administrative port down
133         dataChangedEvent.updated.put(iiToConnector, fcnc);
134
135         // Invoke NodeConnectorInventoryEventTranslator and check result
136         translator.onDataChanged(dataChangedEvent);
137         verify(eventsObserver).nodeConnectorRemoved(id);
138     }
139
140     /**
141      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorAdded} is called
142      * for each FlowCapableNodeConnector item inside @{AsyncDataChangeEvent#getUpdatedData}
143      * that have administrative up and link up state.
144      */
145     @Test
146     public void testNodeConnectorUpdateToUp() {
147         // Setup dataChangedEvent to mock link up and administrative port up
148         dataChangedEvent.updated.put(iiToConnector, fcnc);
149
150         // Invoke NodeConnectorInventoryEventTranslator and check result
151         translator.onDataChanged(dataChangedEvent);
152         verify(eventsObserver).nodeConnectorAdded(id, fcnc);
153     }
154
155     /**
156      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorRemoved} is called
157      * for each FlowCapableNodeConnector path that @{AsyncDataChangeEvent#getRemovedPaths} return.
158      */
159     @Test
160     public void testNodeConnectorRemoval() {
161         // Setup dataChangedEvent to mock node connector removal
162         dataChangedEvent.removed.add(iiToConnector);
163
164         // Invoke NodeConnectorInventoryEventTranslator and check result
165         translator.onDataChanged(dataChangedEvent);
166         verify(eventsObserver).nodeConnectorRemoved(id);
167     }
168
169     /**
170      * Test that checks if @{NodeConnectorEventsObserver#nodeConnectorAdded} and
171      * @{NodeConnectorEventsObserver#nodeConnectorRemoved} are called for each
172      * observer when multiple observers are registered for notifications.
173      */
174     @Test
175     public  void testMultipleObserversNotified() throws Exception {
176         // Create prerequisites
177         InstanceIdentifier<NodeConnector> id2 = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:2");
178         InstanceIdentifier<FlowCapableNodeConnector> iiToConnector2 = id2.augmentation(FlowCapableNodeConnector.class);
179
180         // Setup dataChangedEvent to mock port creation and removal
181         dataChangedEvent.created.put(iiToConnector, fcnc);
182         dataChangedEvent.removed.add(iiToConnector2);
183
184         // Invoke onDataChanged and check that both observers notified
185         translator.onDataChanged(dataChangedEvent);
186         verify(eventsObserver).nodeConnectorAdded(id, fcnc);
187         verify(eventsObserver).nodeConnectorRemoved(id2);
188         verify(eventsObserver2).nodeConnectorAdded(id, fcnc);
189         verify(eventsObserver2).nodeConnectorRemoved(id2);
190     }
191
192     /**
193      * Test that @{ListenerRegistration} is closed when ${NodeConnectorInventoryEventTranslator#close}
194      * method is called.
195      * @throws Exception
196      */
197     @Test
198     public void testCleanup() throws Exception {
199         // Trigger cleanup
200         translator.close();
201
202         // Verify that ListenerRegistration to DOM events
203         verify(dataChangeListenerRegistration, times(2)).close();
204     }
205
206     static class MockDataChangedEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
207         Map<InstanceIdentifier<?>,DataObject> created = new HashMap<>();
208         Map<InstanceIdentifier<?>,DataObject> updated = new HashMap<>();
209         Set<InstanceIdentifier<?>> removed = new HashSet<>();
210
211         @Override
212         public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
213             return created;
214         }
215
216         @Override
217         public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
218             return updated;
219         }
220
221         @Override
222         public Set<InstanceIdentifier<?>> getRemovedPaths() {
223             return removed;
224         }
225
226         @Override
227         public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
228             throw new UnsupportedOperationException("Not implemented by mock");
229         }
230
231         @Override
232         public DataObject getOriginalSubtree() {
233             throw new UnsupportedOperationException("Not implemented by mock");
234         }
235
236         @Override
237         public DataObject getUpdatedSubtree() {
238             throw new UnsupportedOperationException("Not implemented by mock");
239         }
240     }
241 }