2 * Copyright © 2015, 2017 Inocybe Technologies 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.southbound;
11 import static org.junit.Assert.assertEquals;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.anyInt;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
19 import static org.powermock.api.support.membermodification.MemberMatcher.field;
20 import static org.powermock.api.support.membermodification.MemberModifier.suppress;
22 import com.google.common.base.Optional;
23 import com.google.common.util.concurrent.CheckedFuture;
24 import com.google.common.util.concurrent.Futures;
25 import java.net.InetAddress;
26 import java.util.Collections;
27 import java.util.HashMap;
29 import java.util.concurrent.ConcurrentHashMap;
30 import org.junit.Before;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.Mock;
35 import org.mockito.Mockito;
36 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
37 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
39 import org.opendaylight.mdsal.eos.binding.api.Entity;
40 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipChange;
41 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
42 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
43 import org.opendaylight.ovsdb.lib.OvsdbClient;
44 import org.opendaylight.ovsdb.lib.OvsdbConnection;
45 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
46 import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
47 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
48 import org.opendaylight.ovsdb.southbound.transactions.md.TransactionCommand;
49 import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvoker;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAttributes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 import org.opendaylight.yangtools.yang.common.Uint16;
58 import org.powermock.api.mockito.PowerMockito;
59 import org.powermock.api.support.membermodification.MemberMatcher;
60 import org.powermock.api.support.membermodification.MemberModifier;
61 import org.powermock.core.classloader.annotations.PrepareForTest;
62 import org.powermock.modules.junit4.PowerMockRunner;
63 import org.powermock.reflect.Whitebox;
65 @RunWith(PowerMockRunner.class)
66 @PrepareForTest({ SouthboundMapper.class, OvsdbConnectionManager.class, OvsdbConnectionService.class,
67 InstanceIdentifier.class, SouthboundUtil.class, Optional.class })
68 public class OvsdbConnectionManagerTest {
70 @Mock private OvsdbConnectionManager ovsdbConnManager;
71 @Mock private DataBroker db;
72 @Mock private TransactionInvoker txInvoker;
73 @Mock private EntityOwnershipService entityOwnershipService;
74 @Mock private OvsdbConnection ovsdbConnection;
75 @Mock private OvsdbClient externalClient;
76 @Mock private ReconciliationManager reconciliationManager;
77 private Map<ConnectionInfo,OvsdbConnectionInstance> clients;
78 private Map<ConnectionInfo,InstanceIdentifier<Node>> instanceIdentifiers;
79 private Map<Entity, OvsdbConnectionInstance> entityConnectionMap;
81 @Mock private InstanceIdentifier<Node> iid;
84 public void setUp() throws Exception {
85 ovsdbConnManager = PowerMockito.mock(OvsdbConnectionManager.class, Mockito.CALLS_REAL_METHODS);
86 field(OvsdbConnectionManager.class, "db").set(ovsdbConnManager, db);
87 field(OvsdbConnectionManager.class, "txInvoker").set(ovsdbConnManager, txInvoker);
88 field(OvsdbConnectionManager.class, "entityOwnershipService").set(ovsdbConnManager, entityOwnershipService);
89 field(OvsdbConnectionManager.class, "reconciliationManager").set(ovsdbConnManager, reconciliationManager);
90 field(OvsdbConnectionManager.class, "ovsdbConnection").set(ovsdbConnManager, ovsdbConnection);
91 entityConnectionMap = new ConcurrentHashMap<>();
93 OvsdbConnectionInfo info = mock(OvsdbConnectionInfo.class);
94 doReturn(mock(InetAddress.class)).when(info).getRemoteAddress();
95 doReturn(8080).when(info).getRemotePort();
96 doReturn(mock(InetAddress.class)).when(info).getLocalAddress();
97 doReturn(8080).when(info).getLocalPort();
99 externalClient = mock(OvsdbClient.class, Mockito.RETURNS_DEEP_STUBS);
100 doReturn(info).when(externalClient).getConnectionInfo();
101 doReturn(Futures.immediateFuture(Collections.singletonList("Open_vSwitch"))).when(externalClient)
104 PowerMockito.mockStatic(SouthboundUtil.class);
105 when(SouthboundUtil.connectionInfoToString(any(ConnectionInfo.class))).thenReturn("192.18.120.31:8080");
109 public void testConnected() throws Exception {
110 OvsdbConnectionInstance client = mock(OvsdbConnectionInstance.class);
111 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "connectedButCallBacksNotRegistered",
113 when(ovsdbConnManager.connectedButCallBacksNotRegistered(any(OvsdbClient.class))).thenReturn(client);
114 doNothing().when(client).registerCallbacks(any());
116 //TODO: Write unit tests for EntityOwnershipService
117 when(client.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
118 field(OvsdbConnectionManager.class, "entityConnectionMap").set(ovsdbConnManager, entityConnectionMap);
119 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getEntityFromConnectionInstance",
120 OvsdbConnectionInstance.class));
122 //TODO: Write unit tests for entity ownership service related code.
123 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "registerEntityForOwnership",
124 OvsdbConnectionInstance.class));
126 ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class);
127 when(db.newReadOnlyTransaction()).thenReturn(tx);
128 when(tx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
129 .thenReturn(mock(CheckedFuture.class));
130 when(client.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
132 ovsdbConnManager.connected(externalClient);
135 @SuppressWarnings("unchecked")
137 public void testConnectedButCallBacksNotRegistered() throws Exception {
138 ConnectionInfo key = mock(ConnectionInfo.class);
140 PowerMockito.mockStatic(SouthboundMapper.class);
141 when(SouthboundMapper.createConnectionInfo(any(OvsdbClient.class))).thenReturn(key);
143 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getInstanceIdentifier", ConnectionInfo.class));
144 when(ovsdbConnManager.getInstanceIdentifier(key)).thenReturn(mock(InstanceIdentifier.class));
146 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
147 when(ovsdbConnManager.getConnectionInstance(key)).thenReturn(null);
149 OvsdbConnectionInstance client = mock(OvsdbConnectionInstance.class);
150 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "putConnectionInstance", ConnectionInfo.class,
151 OvsdbConnectionInstance.class));
152 doNothing().when(client).createTransactInvokers();
153 PowerMockito.whenNew(OvsdbConnectionInstance.class).withArguments(any(ConnectionInfo.class),
154 any(OvsdbClient.class), any(TransactionInvoker.class), any(InstanceIdentifier.class))
157 assertEquals("Error, did not receive correct OvsdbConnectionInstance object", client,
158 ovsdbConnManager.connectedButCallBacksNotRegistered(externalClient));
162 public void testDisconnected() throws Exception {
163 ConnectionInfo key = mock(ConnectionInfo.class);
164 PowerMockito.mockStatic(SouthboundMapper.class);
165 when(SouthboundMapper.createConnectionInfo(any(OvsdbClient.class))).thenReturn(key);
167 OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
168 clients = new ConcurrentHashMap<>();
169 clients.put(key, ovsdbConnectionInstance);
170 MemberModifier.field(OvsdbConnectionManager.class, "clients").set(ovsdbConnManager, clients);
172 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
173 when(ovsdbConnManager.getConnectionInstance(any(ConnectionInfo.class))).thenReturn(ovsdbConnectionInstance);
174 doNothing().when(txInvoker).invoke(any(TransactionCommand.class));
176 when(SouthboundMapper.suppressLocalIpPort(any(ConnectionInfo.class))).thenReturn(key);
178 // TODO: Write unit tests for EntityOwnershipService
179 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "unregisterEntityForOwnership",
180 OvsdbConnectionInstance.class));
181 instanceIdentifiers = new ConcurrentHashMap<>();
182 field(OvsdbConnectionManager.class, "instanceIdentifiers").set(ovsdbConnManager, instanceIdentifiers);
183 field(OvsdbConnectionManager.class, "nodeIdVsConnectionInstance").set(ovsdbConnManager, new HashMap<>());
185 MemberModifier.suppress(MemberMatcher.method(OvsdbConnectionManager.class, "reconcileConnection",
186 InstanceIdentifier.class, OvsdbNodeAugmentation.class));
187 ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class);
188 when(db.newReadOnlyTransaction()).thenReturn(tx);
189 when(tx.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
190 .thenReturn(mock(CheckedFuture.class));
191 when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
192 ovsdbConnManager.disconnected(externalClient);
193 Map<ConnectionInfo, OvsdbConnectionInstance> testClients = Whitebox.getInternalState(ovsdbConnManager,
195 assertEquals("Error, size of the hashmap is incorrect", 0, testClients.size());
199 public void testDisconnect() throws Exception {
200 OvsdbNodeAugmentation ovsdbNode = mock(OvsdbNodeAugmentation.class);
201 ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
202 when(ovsdbNode.getConnectionInfo()).thenReturn(connectionInfo);
203 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
204 OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
205 when(ovsdbConnManager.getConnectionInstance(any(ConnectionInfo.class))).thenReturn(ovsdbConnectionInstance);
206 when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
208 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "removeInstanceIdentifier", ConnectionInfo.class));
210 // TODO: Write unit tests for entity ownership service related code.
211 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "unregisterEntityForOwnership",
212 OvsdbConnectionInstance.class));
213 ovsdbConnManager.disconnect(ovsdbNode);
214 verify(ovsdbConnectionInstance).disconnect();
219 public void testInit() {
220 mock(ConnectionInfo.class);
221 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
222 OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
223 when(ovsdbConnManager.getConnectionInstance(any(ConnectionInfo.class))).thenReturn(ovsdbConnectionInstance);
226 // ovsdbConnectionManager.init(key);
227 verify(ovsdbConnectionInstance).registerCallbacks(any());
231 public void testClose() throws Exception {
232 ConnectionInfo key1 = mock(ConnectionInfo.class);
233 ConnectionInfo key2 = mock(ConnectionInfo.class);
234 OvsdbConnectionInstance ovsdbConnectionInstance1 = mock(OvsdbConnectionInstance.class);
235 OvsdbConnectionInstance ovsdbConnectionInstance2 = mock(OvsdbConnectionInstance.class);
236 clients = new ConcurrentHashMap<>();
237 clients.put(key1, ovsdbConnectionInstance1);
238 clients.put(key2, ovsdbConnectionInstance2);
239 MemberModifier.field(OvsdbConnectionManager.class, "clients").set(ovsdbConnManager, clients);
240 ovsdbConnManager.close();
241 verify(ovsdbConnectionInstance1).disconnect();
242 verify(ovsdbConnectionInstance2).disconnect();
246 public void testPutAndGetConnectionInstance() throws Exception {
247 ConnectionInfo key = mock(ConnectionInfo.class);
248 ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
249 PowerMockito.mockStatic(SouthboundMapper.class);
250 when(SouthboundMapper.suppressLocalIpPort(key)).thenReturn(connectionInfo);
252 clients = new ConcurrentHashMap<>();
253 MemberModifier.field(OvsdbConnectionManager.class, "clients").set(ovsdbConnManager, clients);
255 // Test putConnectionInstance()
256 OvsdbConnectionInstance instance = mock(OvsdbConnectionInstance.class);
257 Whitebox.invokeMethod(ovsdbConnManager, "putConnectionInstance", key, instance);
258 Map<ConnectionInfo, OvsdbConnectionInstance> testClients = Whitebox.getInternalState(ovsdbConnManager,
260 assertEquals("Error, size of the hashmap is incorrect", 1, testClients.size());
262 // Test getConnectionInstance(ConnectionInfo key)
263 assertEquals("Error, returned incorrect OvsdbConnectionInstance object", instance,
264 ovsdbConnManager.getConnectionInstance(key));
268 public void testPutandGetInstanceIdentifier() throws Exception {
269 ConnectionInfo key = mock(ConnectionInfo.class);
270 ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
271 PowerMockito.mockStatic(SouthboundMapper.class);
272 when(SouthboundMapper.suppressLocalIpPort(key)).thenReturn(connectionInfo);
274 instanceIdentifiers = new ConcurrentHashMap<>();
275 field(OvsdbConnectionManager.class, "instanceIdentifiers").set(ovsdbConnManager, instanceIdentifiers);
277 //Test putInstanceIdentifier()
278 Whitebox.invokeMethod(ovsdbConnManager, "putInstanceIdentifier", key, iid);
279 Map<ConnectionInfo, OvsdbConnectionInstance> testIids = Whitebox.getInternalState(ovsdbConnManager,
280 "instanceIdentifiers");
281 assertEquals("Error, size of the hashmap is incorrect", 1, testIids.size());
283 //Test getInstanceIdentifier()
284 assertEquals("Error returning correct InstanceIdentifier object", iid,
285 ovsdbConnManager.getInstanceIdentifier(key));
287 //Test removeInstanceIdentifier()
288 Whitebox.invokeMethod(ovsdbConnManager, "removeInstanceIdentifier", key);
289 Map<ConnectionInfo, OvsdbConnectionInstance> testRemoveIids = Whitebox.getInternalState(ovsdbConnManager,
290 "instanceIdentifiers");
291 assertEquals("Error, size of the hashmap is incorrect", 0, testRemoveIids.size());
295 public void testGetClient() {
296 OvsdbConnectionInstance ovsdbClient = mock(OvsdbConnectionInstance.class);
297 OvsdbClient client = mock(OvsdbClient.class);
298 when(ovsdbClient.getOvsdbClient()).thenReturn(client);
300 //Test getClient(ConnectionInfo connectionInfo)
301 ConnectionInfo key = mock(ConnectionInfo.class);
302 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
303 when(ovsdbConnManager.getConnectionInstance(key)).thenReturn(ovsdbClient);
304 assertEquals("Error getting correct OvsdbClient object", ovsdbClient.getOvsdbClient(),
305 ovsdbConnManager.getClient(key));
307 //Test getClient(OvsdbBridgeAttributes mn)
308 OvsdbBridgeAttributes mn = mock(OvsdbBridgeAttributes.class);
309 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance",
310 OvsdbBridgeAttributes.class));
311 when(ovsdbConnManager.getConnectionInstance(mn)).thenReturn(ovsdbClient);
312 assertEquals("Error getting correct OvsdbClient object", ovsdbClient.getOvsdbClient(),
313 ovsdbConnManager.getClient(mn));
315 //Test getClient(Node node)
316 Node node = mock(Node.class);
317 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", Node.class));
318 when(ovsdbConnManager.getConnectionInstance(node)).thenReturn(ovsdbClient);
319 assertEquals("Error getting correct OvsdbClient object", ovsdbClient.getOvsdbClient(),
320 ovsdbConnManager.getClient(node));
323 @SuppressWarnings("unchecked")
325 public void testConnect() throws Exception {
326 OvsdbNodeAugmentation ovsdbNode = mock(OvsdbNodeAugmentation.class);
327 ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
328 when(ovsdbNode.getConnectionInfo()).thenReturn(connectionInfo);
329 IpAddress ipAddr = mock(IpAddress.class);
330 when(connectionInfo.getRemoteIp()).thenReturn(ipAddr);
332 PowerMockito.mockStatic(SouthboundMapper.class);
333 InetAddress ip = mock(InetAddress.class);
334 when(SouthboundMapper.createInetAddress(any(IpAddress.class))).thenReturn(ip);
336 PowerMockito.mockStatic(OvsdbConnectionService.class);
337 // when(OvsdbConnectionService.getService()).thenReturn(ovsdbConnection);
338 PortNumber port = mock(PortNumber.class);
339 when(connectionInfo.getRemotePort()).thenReturn(port);
340 when(port.getValue()).thenReturn(Uint16.valueOf(8080));
341 OvsdbClient client = mock(OvsdbClient.class);
342 when(ovsdbConnection.connect(any(InetAddress.class), anyInt())).thenReturn(client);
344 //client not null case
345 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "putInstanceIdentifier", ConnectionInfo.class,
346 InstanceIdentifier.class));
347 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "connectedButCallBacksNotRegistered",
350 doNothing().when(ovsdbConnManager).putInstanceIdentifier(any(ConnectionInfo.class),
351 any(InstanceIdentifier.class));
353 OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
354 when(ovsdbConnManager.connectedButCallBacksNotRegistered(any(OvsdbClient.class)))
355 .thenReturn(ovsdbConnectionInstance);
357 when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
358 field(OvsdbConnectionManager.class, "entityConnectionMap").set(ovsdbConnManager, entityConnectionMap);
359 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getEntityFromConnectionInstance",
360 OvsdbConnectionInstance.class));
361 //TODO: Write unit tests for entity ownership service related code.
362 suppress(MemberMatcher.method(OvsdbConnectionManager.class, "registerEntityForOwnership",
363 OvsdbConnectionInstance.class));
364 assertEquals("ERROR", client, ovsdbConnManager.connect(PowerMockito.mock(InstanceIdentifier.class), ovsdbNode));
368 public void testHandleOwnershipChanged() throws Exception {
369 Entity entity = new Entity("entityType", "entityName");
370 ConnectionInfo key = mock(ConnectionInfo.class);
372 OvsdbConnectionInstance ovsdbConnInstance = new OvsdbConnectionInstance(key, externalClient, txInvoker, iid);
373 entityConnectionMap.put(entity, ovsdbConnInstance);
375 field(OvsdbConnectionManager.class, "entityConnectionMap").set(ovsdbConnManager, entityConnectionMap);
376 doNothing().when(ovsdbConnManager).putConnectionInstance(any(ConnectionInfo.class),
377 any(OvsdbConnectionInstance.class));
378 EntityOwnershipChange ownershipChange = new EntityOwnershipChange(entity,
379 EntityOwnershipChangeState.from(true, false, false));
380 Whitebox.invokeMethod(ovsdbConnManager, "handleOwnershipChanged", ownershipChange);
381 verify(ovsdbConnManager).putConnectionInstance(key, ovsdbConnInstance);