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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * Unit tests for the data-tree change listener.
51 @RunWith(MockitoJUnitRunner.Silent.class)
52 public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
54 static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class);
56 String[][] ucastMacs = new String[][]{
57 {"20:00:00:00:00:01", "11.10.10.1", "192.168.122.20", "ls0"},
58 {"20:00:00:00:00:02", "11.10.10.2", "192.168.122.20", "ls0"},
59 {"20:00:00:00:00:03", "11.10.10.3", "192.168.122.30", "ls1"},
60 {"20:00:00:00:00:04", "11.10.10.4", "192.168.122.30", "ls1"}
63 String[][] logicalSwitches = new String[][]{
68 String[][] terminationPoints = new String[][]{
75 String[][] mcastMacs = new String[][]{
76 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.30"},
77 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"}
80 String[][] mcastMac2 = new String[][]{
81 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.10"},
82 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.20"}
85 String[][] mcastMac3WithZeroLocators = new String[][]{
86 {"FF:FF:FF:FF:FF:FF", "ls0"},
87 {"FF:FF:FF:FF:FF:FF", "ls1"}
90 HwvtepOperationalDataChangeListener opDataChangeListener;
93 public void setupListener() throws Exception {
94 setFinalStatic(DependencyQueue.class, "EXECUTOR_SERVICE", mock(SameThreadScheduledExecutor.class,
95 Mockito.CALLS_REAL_METHODS));
96 opDataChangeListener = new HwvtepOperationalDataChangeListener(dataBroker, hwvtepConnectionManager,
101 public void cleanupListener() throws Exception {
102 opDataChangeListener.close();
106 public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
107 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
108 verifyThatLogicalSwitchCreated();
112 public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
113 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
114 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
116 deleteData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
117 verify(Operations.op, times(10)).delete(any());
121 public <T extends DataObject> void testUcastMacAdd() throws Exception {
122 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
123 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
125 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
126 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
127 //4 ucast macs + 2 termination points
128 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
129 //TODO add finer grained validation
133 public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
134 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
135 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
137 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
138 //4 ucast macs + 2 termination points
139 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
140 //TODO add finer grained validation
144 public <T extends DataObject> void testUcastMacDelete() throws Exception {
145 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
146 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
147 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
148 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
149 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
150 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
153 deleteData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
154 verify(Operations.op, times(4)).delete(any());
155 //TODO add finer grained validation
159 public <T extends DataObject> void testMcastMacAdd() throws Exception {
160 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
161 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
163 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
164 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
165 //2 mcast macs + 2 locator sets + 3 termination points
166 verify(Operations.op, times(7)).insert(ArgumentMatchers.<McastMacsRemote>any());
170 public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
171 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
172 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
174 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
175 //2 mcast macs + 2 locator sets + 3 termination points
176 verify(Operations.op, times(7)).insert(ArgumentMatchers.<McastMacsRemote>any());
180 public <T extends DataObject> void testMcastMacDelete() throws Exception {
181 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
182 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
183 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
184 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
185 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
186 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
189 deleteData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
190 verify(Operations.op, times(2)).delete(ArgumentMatchers.any());
194 public <T extends DataObject> void testAddMacs() throws Exception {
195 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
196 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
198 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
199 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
200 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
202 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
203 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
205 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
206 //2 mcast mac + 2 locator sets ( termination point already added )
207 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
211 public <T extends DataObject> void testUpdateMacs() throws Exception {
212 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
213 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
215 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
216 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
217 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
219 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
220 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
222 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
223 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
224 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
227 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
228 verify(Operations.op, times(2)).insert(ArgumentMatchers.<McastMacsRemote>any());
229 verify(Operations.op, times(2)).update(ArgumentMatchers.<McastMacsRemote>any());
230 verify(Operations.op, times(0)).delete(ArgumentMatchers.any());
234 public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
235 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
236 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
238 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
239 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
240 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
242 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
243 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
245 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
246 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
247 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
250 final MacAddress macAddr = new MacAddress("FF:FF:FF:FF:FF:FF");
251 final InstanceIdentifier<HwvtepGlobalAugmentation> augIid =
252 nodeIid.augmentation(HwvtepGlobalAugmentation.class);
253 deleteData(LogicalDatastoreType.CONFIGURATION,
254 augIid.child(RemoteMcastMacs.class,
255 new RemoteMcastMacsKey(TestBuilders.buildLogicalSwitchesRef(nodeIid, "ls0"), macAddr))
256 .child(LocatorSet.class),
257 augIid.child(RemoteMcastMacs.class,
258 new RemoteMcastMacsKey(TestBuilders.buildLogicalSwitchesRef(nodeIid, "ls1"), macAddr))
259 .child(LocatorSet.class));
260 verify(Operations.op, times(2)).delete(ArgumentMatchers.any());
264 public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
265 addData(LogicalDatastoreType.CONFIGURATION, LogicalSwitches.class, logicalSwitches);
266 addData(LogicalDatastoreType.OPERATIONAL, LogicalSwitches.class, logicalSwitches);
268 addData(LogicalDatastoreType.CONFIGURATION, TerminationPoint.class, terminationPoints);
269 addData(LogicalDatastoreType.CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
270 verify(Operations.op, times(4)).insert(any(UcastMacsRemote.class));
273 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
274 //2 mcast mac + 2 locator sets ( termination point already added )
275 verify(Operations.op, times(0)).insert(ArgumentMatchers.<McastMacsRemote>any());
277 addData(LogicalDatastoreType.OPERATIONAL, TerminationPoint.class, terminationPoints);
278 addData(LogicalDatastoreType.OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
279 connectionInstance.getDeviceInfo().onOperDataAvailable();
280 //2 mcast mac + 2 locator sets ( termination point already added )
281 verify(Operations.op, times(4)).insert(ArgumentMatchers.<McastMacsRemote>any());
284 addData(LogicalDatastoreType.CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
285 verify(Operations.op, times(0)).insert(ArgumentMatchers.<McastMacsRemote>any());
286 addData(LogicalDatastoreType.OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
287 connectionInstance.getDeviceInfo().onOperDataAvailable();
288 verify(Operations.op, times(2)).insert(ArgumentMatchers.<McastMacsRemote>any());
289 verify(Operations.op, times(2)).update(ArgumentMatchers.<McastMacsRemote>any());
292 private void verifyThatLogicalSwitchCreated() {
293 //The transactions could be firing in two different mdsal updates intermittently
294 //verify(ovsdbClient, times(1)).transact(any(DatabaseSchema.class), any(List.class));
295 verify(Operations.op, times(2)).insert(any(LogicalSwitch.class));
297 assertNotNull(insertOpCapture.getAllValues());
298 assertTrue(insertOpCapture.getAllValues().size() == 2);
300 List<String> expected = Lists.newArrayList("ls0", "ls1");
301 Iterator<TypedBaseTable> it = insertOpCapture.getAllValues().iterator();
302 while (it.hasNext()) {
303 TypedBaseTable table = it.next();
304 assertTrue(table instanceof LogicalSwitch);
305 LogicalSwitch ls = (LogicalSwitch)table;
306 assertTrue(expected.contains(ls.getName()));
307 expected.remove(ls.getName());