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.Matchers.any;
14 import static org.mockito.Mockito.times;
15 import static org.mockito.Mockito.verify;
16 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
17 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
19 import com.google.common.collect.Lists;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22 import java.util.Iterator;
23 import java.util.List;
24 import org.apache.commons.lang3.reflect.FieldUtils;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.Matchers;
30 import org.mockito.Mockito;
31 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
32 import org.opendaylight.ovsdb.lib.operations.Operations;
33 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
34 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
35 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
36 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
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.RemoteUcastMacs;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.powermock.api.mockito.PowerMockito;
43 import org.powermock.core.classloader.annotations.PrepareForTest;
44 import org.powermock.modules.junit4.PowerMockRunner;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * Unit tests for the data-tree change listener.
51 @RunWith(PowerMockRunner.class)
52 @PrepareForTest({HwvtepConnectionInstance.class, HwvtepConnectionManager.class, Operations.class})
53 public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
55 static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class);
57 String[][] ucastMacs = new String[][]{
58 {"20:00:00:00:00:01", "11.10.10.1", "192.168.122.20", "ls0"},
59 {"20:00:00:00:00:02", "11.10.10.2", "192.168.122.20", "ls0"},
60 {"20:00:00:00:00:03", "11.10.10.3", "192.168.122.30", "ls1"},
61 {"20:00:00:00:00:04", "11.10.10.4", "192.168.122.30", "ls1"}
64 String[][] logicalSwitches = new String[][]{
69 String[][] terminationPoints = new String[][]{
76 String[][] mcastMacs = new String[][]{
77 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.30"},
78 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"}
81 String[][] mcastMac2 = new String[][]{
82 {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.10"},
83 {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.20"}
86 String[][] mcastMac3WithZeroLocators = new String[][]{
87 {"FF:FF:FF:FF:FF:FF", "ls0"},
88 {"FF:FF:FF:FF:FF:FF", "ls1"}
91 HwvtepOperationalDataChangeListener opDataChangeListener;
94 public void setupListener() throws Exception {
95 setFinalStatic(DependencyQueue.class, "EXECUTOR_SERVICE", PowerMockito.mock(SameThreadScheduledExecutor.class,
96 Mockito.CALLS_REAL_METHODS));
97 opDataChangeListener = new HwvtepOperationalDataChangeListener(dataBroker, hwvtepConnectionManager,
102 public void cleanupListener() throws Exception {
103 opDataChangeListener.close();
107 void setFinalStatic(Class cls, String fieldName, Object newValue) throws Exception {
108 Field[] fields = FieldUtils.getAllFields(cls);
109 for (Field field : fields) {
110 if (fieldName.equals(field.getName())) {
111 field.setAccessible(true);
112 Field modifiersField = Field.class.getDeclaredField("modifiers");
113 modifiersField.setAccessible(true);
114 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
115 field.set(null, newValue);
122 public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
123 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
124 verifyThatLogicalSwitchCreated();
128 public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
129 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
130 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
132 deleteData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
133 verify(Operations.op, times(10)).delete(any());
137 public <T extends DataObject> void testUcastMacAdd() throws Exception {
138 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
139 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
141 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
142 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
143 //4 ucast macs + 2 termination points
144 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
145 //TODO add finer grained validation
149 public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
150 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
151 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
153 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
154 //4 ucast macs + 2 termination points
155 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
156 //TODO add finer grained validation
160 public <T extends DataObject> void testUcastMacDelete() throws Exception {
161 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
162 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
163 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
164 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
165 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
166 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
169 deleteData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
170 verify(Operations.op, times(4)).delete(any());
171 //TODO add finer grained validation
175 public <T extends DataObject> void testMcastMacAdd() throws Exception {
176 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
177 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
179 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
180 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
181 //2 mcast macs + 2 locator sets + 3 termination points
182 verify(Operations.op, times(7)).insert(Matchers.<McastMacsRemote>any());
186 public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
187 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
188 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
190 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
191 //2 mcast macs + 2 locator sets + 3 termination points
192 verify(Operations.op, times(7)).insert(Matchers.<McastMacsRemote>any());
196 public <T extends DataObject> void testMcastMacDelete() throws Exception {
197 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
198 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
199 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
200 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
201 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
202 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
205 deleteData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
206 verify(Operations.op, times(2)).delete(Matchers.any());
210 public <T extends DataObject> void testAddMacs() throws Exception {
211 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
212 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
214 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
215 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
216 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
218 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
219 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
221 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
222 //2 mcast mac + 2 locator sets ( termination point already added )
223 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
227 public <T extends DataObject> void testUpdateMacs() throws Exception {
228 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
229 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
231 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
232 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
233 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
235 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
236 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
238 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
239 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
240 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
243 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
244 verify(Operations.op, times(2)).insert(Matchers.<McastMacsRemote>any());
245 verify(Operations.op, times(2)).update(Matchers.<McastMacsRemote>any());
246 verify(Operations.op, times(0)).delete(Matchers.any());
250 public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
251 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
252 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
254 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
255 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
256 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
258 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
259 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
261 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
262 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
263 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
266 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac3WithZeroLocators);
267 verify(Operations.op, times(2)).delete(Matchers.any());
271 public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
272 addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
273 addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
275 addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
276 addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
277 verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class));
280 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
281 //2 mcast mac + 2 locator sets ( termination point already added )
282 verify(Operations.op, times(0)).insert(Matchers.<McastMacsRemote>any());
284 addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
285 addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
286 connectionInstance.getDeviceInfo().onOperDataAvailable();
287 //2 mcast mac + 2 locator sets ( termination point already added )
288 verify(Operations.op, times(4)).insert(Matchers.<McastMacsRemote>any());
291 addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
292 verify(Operations.op, times(0)).insert(Matchers.<McastMacsRemote>any());
293 addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
294 connectionInstance.getDeviceInfo().onOperDataAvailable();
295 verify(Operations.op, times(2)).insert(Matchers.<McastMacsRemote>any());
296 verify(Operations.op, times(2)).update(Matchers.<McastMacsRemote>any());
299 private void verifyThatLogicalSwitchCreated() {
300 //The transactions could be firing in two different mdsal updates intermittently
301 //verify(ovsdbClient, times(1)).transact(any(DatabaseSchema.class), any(List.class));
302 verify(Operations.op, times(2)).insert(any(LogicalSwitch.class));
304 assertNotNull(insertOpCapture.getAllValues());
305 assertTrue(insertOpCapture.getAllValues().size() == 2);
307 List<String> expected = Lists.newArrayList("ls0", "ls1");
308 Iterator<TypedBaseTable> it = insertOpCapture.getAllValues().iterator();
309 while (it.hasNext()) {
310 TypedBaseTable table = it.next();
311 assertTrue(table instanceof LogicalSwitch);
312 LogicalSwitch ls = (LogicalSwitch)table;
313 assertTrue(expected.contains(ls.getName()));
314 expected.remove(ls.getName());