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