bug 6579 removed boilerplate code
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / test / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepDataChangeListenerTest.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.ovsdb.hwvtepsouthbound;
10
11 import com.google.common.collect.Lists;
12 import com.google.common.util.concurrent.MoreExecutors;
13 import org.apache.commons.lang3.reflect.FieldUtils;
14 import org.junit.After;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 import org.mockito.Matchers;
19 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
20 import org.opendaylight.ovsdb.lib.operations.Operations;
21 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
22 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
23 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
24 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
25 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.powermock.core.classloader.annotations.PrepareForTest;
33 import org.powermock.modules.junit4.PowerMockRunner;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import java.lang.reflect.Field;
38 import java.lang.reflect.Modifier;
39 import java.util.Iterator;
40 import java.util.List;
41
42 import static org.junit.Assert.assertNotNull;
43 import static org.junit.Assert.assertTrue;
44 import static org.mockito.Matchers.any;
45 import static org.mockito.Mockito.times;
46 import static org.mockito.Mockito.verify;
47 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
48 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
49
50 /**
51  * Unit tests for the data-tree change listener.
52  */
53 @RunWith(PowerMockRunner.class)
54 @PrepareForTest({HwvtepConnectionInstance.class, HwvtepConnectionManager.class, Operations.class})
55 public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
56
57     static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class);
58
59     String[][] ucastMacs = new String[][]{
60             {"20:00:00:00:00:01", "11.10.10.1", "192.168.122.20", "ls0"},
61             {"20:00:00:00:00:02", "11.10.10.2", "192.168.122.20", "ls0"},
62             {"20:00:00:00:00:03", "11.10.10.3", "192.168.122.30", "ls1"},
63             {"20:00:00:00:00:04", "11.10.10.4", "192.168.122.30", "ls1"}
64     };
65
66     String[][] logicalSwitches = new String[][]{
67             {"ls0", "100"},
68             {"ls1", "200"},
69     };
70
71     String[][] terminationPoints = new String[][]{
72             {"192.168.122.10"},
73             {"192.168.122.20"},
74             {"192.168.122.30"},
75             {"192.168.122.40"}
76     };
77
78     String[][] mcastMacs = new String[][]{
79             {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.30"},
80             {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"}
81     };
82
83     String[][] mcastMac2 = new String[][]{
84             {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.10"},
85             {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.20"}
86     };
87
88     String[][] mcastMac3WithZeroLocators = new String[][]{
89             {"FF:FF:FF:FF:FF:FF", "ls0"},
90             {"FF:FF:FF:FF:FF:FF", "ls1"}
91     };
92
93     HwvtepOperationalDataChangeListener opDataChangeListener;
94
95     @Before
96     public void setupListener() throws Exception {
97         setFinalStatic(DependencyQueue.class, "executorService", MoreExecutors.sameThreadExecutor());
98         opDataChangeListener = new HwvtepOperationalDataChangeListener(dataBroker, hwvtepConnectionManager, connectionInstance);
99     }
100
101     @After
102     public void cleanupListener() {
103         try {
104             opDataChangeListener.close();
105         } catch (Exception e) {
106         }
107     }
108
109     void setFinalStatic(Class cls, String fieldName, Object newValue) throws Exception {
110         Field fields[] = FieldUtils.getAllFields(cls);
111         for (Field field : fields) {
112             if (fieldName.equals(field.getName())) {
113                 field.setAccessible(true);
114                 Field modifiersField = Field.class.getDeclaredField("modifiers");
115                 modifiersField.setAccessible(true);
116                 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
117                 field.set(null, newValue);
118                 break;
119             }
120         }
121     }
122
123     @Test
124     public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
125         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
126         verifyThatLogicalSwitchCreated();
127     }
128
129     @Test
130     public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
131         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
132         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
133         resetOperations();
134         deleteData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
135         verify(Operations.op,  times(2)).delete(any());
136     }
137
138     @Test
139     public <T extends DataObject> void testUcastMacAdd() throws Exception {
140         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
141         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
142         resetOperations();
143         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
144         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
145         //4 ucast macs + 2 termination points
146         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
147         //TODO add finer grained validation
148     }
149
150     @Test
151     public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
152         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
153         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
154         resetOperations();
155         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
156         //4 ucast macs + 2 termination points
157         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
158         //TODO add finer grained validation
159     }
160
161     @Test
162     public <T extends DataObject> void testUcastMacDelete() throws Exception {
163         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
164         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
165         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
166         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
167         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
168         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
169
170         resetOperations();
171         deleteData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
172         verify(Operations.op,  times(4)).delete(any());
173         //TODO add finer grained validation
174     }
175
176     @Test
177     public <T extends DataObject> void testMcastMacAdd() throws Exception {
178         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
179         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
180         resetOperations();
181         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
182         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
183         //2 mcast macs + 2 locator sets + 3 termination points
184         verify(Operations.op,  times(7)).insert(Matchers.<McastMacsRemote>any());
185     }
186
187     @Test
188     public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
189         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
190         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
191         resetOperations();
192         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
193         //2 mcast macs + 2 locator sets + 3 termination points
194         verify(Operations.op,  times(7)).insert(Matchers.<McastMacsRemote>any());
195     }
196
197     @Test
198     public <T extends DataObject> void testMcastMacDelete() throws Exception {
199         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
200         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
201         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
202         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
203         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
204         addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
205
206         resetOperations();
207         deleteData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
208         verify(Operations.op,  times(2)).delete(Matchers.any());
209     }
210
211     @Test
212     public <T extends DataObject> void testAddMacs() throws Exception {
213         Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
214         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
215         resetOperations();
216         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
217         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
218         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
219
220         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
221         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
222         resetOperations();
223         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
224         //2 mcast mac + 2 locator sets ( termination point already added )
225         verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
226     }
227
228     @Test
229     public <T extends DataObject> void testUpdateMacs() throws Exception {
230         Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
231         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
232         resetOperations();
233         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
234         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
235         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
236
237         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
238         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
239         resetOperations();
240         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
241         verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
242         addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
243
244         resetOperations();
245         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
246         verify(Operations.op,  times(2)).insert(Matchers.<McastMacsRemote>any());
247         verify(Operations.op,  times(2)).update(Matchers.<McastMacsRemote>any());
248         verify(Operations.op,  times(0)).delete(Matchers.any());
249     }
250
251     @Test
252     public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
253         Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
254         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
255         resetOperations();
256         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
257         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
258         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
259
260         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
261         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
262         resetOperations();
263         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
264         verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
265         addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
266
267         resetOperations();
268         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac3WithZeroLocators);
269         verify(Operations.op,  times(2)).delete(Matchers.any());
270     }
271
272     @Test
273     public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
274         Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
275         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
276         resetOperations();
277         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
278         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
279         verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
280
281         resetOperations();
282         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
283         //2 mcast mac + 2 locator sets ( termination point already added )
284         verify(Operations.op,  times(0)).insert(Matchers.<McastMacsRemote>any());
285         resetOperations();
286         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
287         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
288         connectionInstance.getDeviceInfo().onOpDataAvailable();
289         //2 mcast mac + 2 locator sets ( termination point already added )
290         verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
291
292         resetOperations();
293         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
294         verify(Operations.op,  times(0)).insert(Matchers.<McastMacsRemote>any());
295         addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
296         connectionInstance.getDeviceInfo().onOpDataAvailable();
297         verify(Operations.op,  times(2)).insert(Matchers.<McastMacsRemote>any());
298         verify(Operations.op,  times(2)).update(Matchers.<McastMacsRemote>any());
299     }
300
301     private void verifyThatLogicalSwitchCreated() {
302         verify(ovsdbClient, times(1)).transact(any(DatabaseSchema.class), any(List.class));
303         verify(Operations.op, times(2)).insert(any(LogicalSwitch.class));
304
305         assertNotNull(insertOpCapture.getAllValues());
306         assertTrue(insertOpCapture.getAllValues().size() == 2);
307
308         List<String> expected = Lists.newArrayList("ls0", "ls1");
309         Iterator<TypedBaseTable> it = insertOpCapture.getAllValues().iterator();
310         while (it.hasNext()) {
311             TypedBaseTable table = it.next();
312             assertTrue(table instanceof LogicalSwitch);
313             LogicalSwitch ls = (LogicalSwitch)table;
314             assertTrue(expected.contains(ls.getName()));
315             expected.remove(ls.getName());
316             it.next();
317         }
318     }
319 }