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 com.google.common.collect.Lists;
12 import org.apache.commons.lang3.reflect.FieldUtils;
13 import org.junit.After;
14 import org.junit.Before;
15 import org.junit.Test;
16 import org.junit.runner.RunWith;
17 import org.mockito.Matchers;
18 import org.mockito.Mockito;
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.api.mockito.PowerMockito;
33 import org.powermock.core.classloader.annotations.PrepareForTest;
34 import org.powermock.modules.junit4.PowerMockRunner;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import java.lang.reflect.Field;
39 import java.lang.reflect.Modifier;
40 import java.util.Iterator;
41 import java.util.List;
43 import static org.junit.Assert.assertNotNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.mockito.Matchers.any;
46 import static org.mockito.Mockito.times;
47 import static org.mockito.Mockito.verify;
48 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
49 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
52 * Unit tests for the data-tree change listener.
54 @RunWith(PowerMockRunner.class)
55 @PrepareForTest({HwvtepConnectionInstance.class, HwvtepConnectionManager.class, Operations.class})
56 public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
58 static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class);
60 String[][] ucastMacs = new String[][]{
61 {"20:00:00:00:00:01", "11.10.10.1", "192.168.122.20", "ls0"},
62 {"20:00:00:00:00:02", "11.10.10.2", "192.168.122.20", "ls0"},
63 {"20:00:00:00:00:03", "11.10.10.3", "192.168.122.30", "ls1"},
64 {"20:00:00:00:00:04", "11.10.10.4", "192.168.122.30", "ls1"}
67 String[][] logicalSwitches = new String[][]{
72 String[][] terminationPoints = new String[][]{
79 String[][] mcastMacs = new String[][]{
80 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.30"},
81 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"}
84 String[][] mcastMac2 = new String[][]{
85 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.10"},
86 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.20"}
89 String[][] mcastMac3WithZeroLocators = new String[][]{
90 {"FF:FF:FF:FF:FF:FF", "ls0"},
91 {"FF:FF:FF:FF:FF:FF", "ls1"}
94 HwvtepOperationalDataChangeListener opDataChangeListener;
97 public void setupListener() throws Exception {
98 setFinalStatic(DependencyQueue.class, "executorService", PowerMockito.mock(SameThreadScheduledExecutor.class, Mockito.CALLS_REAL_METHODS));
99 opDataChangeListener = new HwvtepOperationalDataChangeListener(dataBroker, hwvtepConnectionManager, connectionInstance);
103 public void cleanupListener() {
105 opDataChangeListener.close();
106 } catch (Exception e) {
110 void setFinalStatic(Class cls, String fieldName, Object newValue) throws Exception {
111 Field fields[] = FieldUtils.getAllFields(cls);
112 for (Field field : fields) {
113 if (fieldName.equals(field.getName())) {
114 field.setAccessible(true);
115 Field modifiersField = Field.class.getDeclaredField("modifiers");
116 modifiersField.setAccessible(true);
117 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
118 field.set(null, newValue);
125 public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
126 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
127 verifyThatLogicalSwitchCreated();
131 public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
132 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
133 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
135 deleteData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
136 verify(Operations.op, times(10)).delete(any());
140 public <T extends DataObject> void testUcastMacAdd() throws Exception {
141 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
142 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
144 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
145 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
146 //4 ucast macs + 2 termination points
147 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
148 //TODO add finer grained validation
152 public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
153 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
154 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
156 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
157 //4 ucast macs + 2 termination points
158 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
159 //TODO add finer grained validation
163 public <T extends DataObject> void testUcastMacDelete() throws Exception {
164 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
165 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
166 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
167 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
168 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
169 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
172 deleteData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
173 verify(Operations.op, times(4)).delete(any());
174 //TODO add finer grained validation
178 public <T extends DataObject> void testMcastMacAdd() throws Exception {
179 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
180 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
182 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
183 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
184 //2 mcast macs + 2 locator sets + 3 termination points
185 verify(Operations.op, times(7)).insert(Matchers.<McastMacsRemote>any());
189 public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
190 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
191 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
193 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
194 //2 mcast macs + 2 locator sets + 3 termination points
195 verify(Operations.op, times(7)).insert(Matchers.<McastMacsRemote>any());
199 public <T extends DataObject> void testMcastMacDelete() throws Exception {
200 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
201 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
202 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
203 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
204 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
205 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
208 deleteData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
209 verify(Operations.op, times(2)).delete(Matchers.any());
213 public <T extends DataObject> void testAddMacs() throws Exception {
214 Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
215 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
217 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
218 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
219 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
221 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
222 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
224 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
225 //2 mcast mac + 2 locator sets ( termination point already added )
226 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
230 public <T extends DataObject> void testUpdateMacs() throws Exception {
231 Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
232 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
234 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
235 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
236 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
238 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
239 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
241 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
242 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
243 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
246 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
247 verify(Operations.op, times(2)).insert(Matchers.<McastMacsRemote>any());
248 verify(Operations.op, times(2)).update(Matchers.<McastMacsRemote>any());
249 verify(Operations.op, times(0)).delete(Matchers.any());
253 public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
254 Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
255 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
257 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
258 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
259 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
261 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
262 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
264 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
265 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
266 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
269 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac3WithZeroLocators);
270 verify(Operations.op, times(2)).delete(Matchers.any());
274 public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
275 Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
276 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
278 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
279 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
280 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
283 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
284 //2 mcast mac + 2 locator sets ( termination point already added )
285 verify(Operations.op, times(0)).insert(Matchers.<McastMacsRemote>any());
287 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
288 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
289 connectionInstance.getDeviceInfo().onOperDataAvailable();
290 //2 mcast mac + 2 locator sets ( termination point already added )
291 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
294 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
295 verify(Operations.op, times(0)).insert(Matchers.<McastMacsRemote>any());
296 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
297 connectionInstance.getDeviceInfo().onOperDataAvailable();
298 verify(Operations.op, times(2)).insert(Matchers.<McastMacsRemote>any());
299 verify(Operations.op, times(2)).update(Matchers.<McastMacsRemote>any());
302 private void verifyThatLogicalSwitchCreated() {
303 verify(ovsdbClient, times(1)).transact(any(DatabaseSchema.class), any(List.class));
304 verify(Operations.op, times(2)).insert(any(LogicalSwitch.class));
306 assertNotNull(insertOpCapture.getAllValues());
307 assertTrue(insertOpCapture.getAllValues().size() == 2);
309 List<String> expected = Lists.newArrayList("ls0", "ls1");
310 Iterator<TypedBaseTable> it = insertOpCapture.getAllValues().iterator();
311 while (it.hasNext()) {
312 TypedBaseTable table = it.next();
313 assertTrue(table instanceof LogicalSwitch);
314 LogicalSwitch ls = (LogicalSwitch)table;
315 assertTrue(expected.contains(ls.getName()));
316 expected.remove(ls.getName());