2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. 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.ovsdb.hwvtepsouthbound;
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;
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;
44 * Unit tests for the data-tree change listener.
46 @RunWith(MockitoJUnitRunner.Silent.class)
47 public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
49 static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class);
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"}
58 String[][] logicalSwitches = new String[][]{
63 String[][] terminationPoints = new String[][]{
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"}
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"}
80 String[][] mcastMac3WithZeroLocators = new String[][]{
81 {"FF:FF:FF:FF:FF:FF", "ls0"},
82 {"FF:FF:FF:FF:FF:FF", "ls1"}
85 HwvtepOperationalDataChangeListener opDataChangeListener;
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,
96 public void cleanupListener() throws Exception {
97 opDataChangeListener.close();
101 public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
102 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
103 verifyThatLogicalSwitchCreated();
107 public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
108 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
109 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
111 deleteData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
112 verify(Operations.op, times(10)).delete(any());
116 public <T extends DataObject> void testUcastMacAdd() throws Exception {
117 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
118 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
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
128 public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
129 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
130 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
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
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);
148 deleteData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
149 verify(Operations.op, times(4)).delete(any());
150 //TODO add finer grained validation
154 public <T extends DataObject> void testMcastMacAdd() throws Exception {
155 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
156 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
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());
165 public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
166 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
167 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
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());
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);
184 deleteData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
185 verify(Operations.op, times(2)).delete(ArgumentMatchers.any());
189 public <T extends DataObject> void testAddMacs() throws Exception {
190 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
191 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
193 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
194 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
195 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
197 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
198 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
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());
206 public <T extends DataObject> void testUpdateMacs() throws Exception {
207 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
208 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
210 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
211 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
212 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
214 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
215 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
217 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
218 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
219 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
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());
229 public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
230 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
231 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
233 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
234 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
235 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
237 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
238 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
240 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
241 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
242 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
245 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMac3WithZeroLocators);
246 verify(Operations.op, times(2)).delete(ArgumentMatchers.any());
250 public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
251 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
252 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
254 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
255 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
256 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
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());
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());
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());
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));
283 assertNotNull(insertOpCapture.getAllValues());
284 assertTrue(insertOpCapture.getAllValues().size() == 2);
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());