bug 6579 removed boilerplate code
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / test / java / org / opendaylight / ovsdb / hwvtepsouthbound / DataChangeListenerTestBase.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.ovsdb.hwvtepsouthbound;
10
11 import com.fasterxml.jackson.databind.JsonNode;
12 import com.fasterxml.jackson.databind.ObjectMapper;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.junit.After;
15 import org.junit.Before;
16 import org.mockito.ArgumentCaptor;
17 import org.mockito.Mockito;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
22 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker;
25 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
26 import org.opendaylight.ovsdb.lib.OvsdbClient;
27 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
28 import org.opendaylight.ovsdb.lib.operations.Delete;
29 import org.opendaylight.ovsdb.lib.operations.Insert;
30 import org.opendaylight.ovsdb.lib.operations.OperationResult;
31 import org.opendaylight.ovsdb.lib.operations.Operations;
32 import org.opendaylight.ovsdb.lib.operations.Update;
33 import org.opendaylight.ovsdb.lib.operations.Where;
34 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
35 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
53 import org.opendaylight.yangtools.yang.binding.DataObject;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.powermock.api.mockito.PowerMockito;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import java.io.InputStream;
60 import java.net.InetAddress;
61 import java.util.List;
62
63 import static org.mockito.Matchers.any;
64 import static org.mockito.Matchers.anyString;
65 import static org.mockito.Mockito.doReturn;
66 import static org.mockito.Mockito.mock;
67 import static org.mockito.Mockito.when;
68 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
69 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
70 import static org.powermock.api.support.membermodification.MemberMatcher.field;
71 import static org.powermock.api.support.membermodification.MemberModifier.suppress;
72
73 public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
74
75     static Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class);
76
77     static DataBroker dataBroker;
78
79     EntityOwnershipService entityOwnershipService;
80     OvsdbClient ovsdbClient;
81     DatabaseSchema dbSchema;
82     ListenableFuture<DatabaseSchema> listenableDbSchema = mock(ListenableFuture.class);
83     TransactionInvoker transactionInvoker;
84     OvsdbConnectionInfo connectionInfo;
85     Operations operations;
86     HwvtepDataChangeListener hwvtepDataChangeListener;
87     HwvtepConnectionManager hwvtepConnectionManager;
88     HwvtepConnectionInstance connectionInstance;
89
90     ArgumentCaptor<TypedBaseTable> insertOpCapture;
91     ArgumentCaptor<List> transactCaptor;
92
93     String nodeUuid;
94     InstanceIdentifier<Node> nodeIid;
95     InstanceIdentifier<LogicalSwitches> ls0Iid;
96     InstanceIdentifier<LogicalSwitches> ls1Iid;
97
98     @Before
99     public void setupTest() throws Exception {
100         /**
101          *  Use the same databroker across tests ,otherwise the following exception is thrown
102          *  Caused by: java.lang.RuntimeException: org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.
103          *  topology.rev131021.node.attributes.SupportingNode$StreamWriter: frozen class (cannot edit)
104          */
105         if (dataBroker == null) {
106             dataBroker = super.getDataBroker();
107         }
108         entityOwnershipService = mock(EntityOwnershipService.class);
109         nodeUuid = java.util.UUID.randomUUID().toString();
110         nodeIid = createInstanceIdentifier(nodeUuid);
111         ls0Iid = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
112                 child(LogicalSwitches.class, new LogicalSwitchesKey(new HwvtepNodeName("ls0")));
113         ls1Iid = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
114                 child(LogicalSwitches.class, new LogicalSwitchesKey(new HwvtepNodeName("ls1")));
115         loadSchema();
116         mockConnectionInstance();
117         mockConnectionManager();
118         mockOperations();
119
120         addNode(OPERATIONAL);
121         addNode(CONFIGURATION);
122         hwvtepDataChangeListener = new HwvtepDataChangeListener(dataBroker, hwvtepConnectionManager);
123     }
124
125     @After
126     public void tearDown() throws Exception {
127         hwvtepDataChangeListener.close();
128         deleteNode(OPERATIONAL);
129         deleteNode(CONFIGURATION);
130     }
131
132     void loadSchema() {
133         try (InputStream resourceAsStream = DataChangeListenerTestBase.class.getResourceAsStream("hwvtep_schema.json")) {
134             ObjectMapper mapper = new ObjectMapper();
135             JsonNode jsonNode = mapper.readTree(resourceAsStream);
136             dbSchema = DatabaseSchema.fromJson(HwvtepSchemaConstants.HARDWARE_VTEP,
137                     jsonNode.get("result"));
138             listenableDbSchema = mock(ListenableFuture.class);
139             when(listenableDbSchema.get()).thenReturn(dbSchema);
140         } catch (Exception e) {
141             LOG.error("Failed to load schema", e);
142         }
143     }
144
145     private void mockConnectionManager() throws IllegalAccessException {
146         hwvtepConnectionManager = PowerMockito.mock(HwvtepConnectionManager.class, Mockito.CALLS_REAL_METHODS);
147         field(HwvtepConnectionManager.class, "db").set(hwvtepConnectionManager, dataBroker);
148         field(HwvtepConnectionManager.class, "txInvoker").set(hwvtepConnectionManager, transactionInvoker);
149         field(HwvtepConnectionManager.class, "entityOwnershipService").set(hwvtepConnectionManager, entityOwnershipService);
150         suppress(PowerMockito.method(HwvtepConnectionManager.class, "getConnectionInstance", HwvtepPhysicalSwitchAttributes.class));
151         when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(HwvtepPhysicalSwitchAttributes.class))).
152                 thenReturn(connectionInstance);
153         when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(Node.class))).
154                 thenReturn(connectionInstance);
155     }
156
157     void mockConnectionInstance() throws IllegalAccessException {
158         connectionInfo = mock(OvsdbConnectionInfo.class);
159         ovsdbClient = mock(OvsdbClient.class);
160         transactionInvoker =  new TransactionInvokerImpl(dataBroker);
161
162         connectionInstance = PowerMockito.mock(HwvtepConnectionInstance.class, Mockito.CALLS_REAL_METHODS);
163         field(HwvtepConnectionInstance.class, "instanceIdentifier").set(connectionInstance, nodeIid);
164         field(HwvtepConnectionInstance.class, "txInvoker").set(connectionInstance, transactionInvoker);
165         field(HwvtepConnectionInstance.class, "deviceInfo").set(connectionInstance, new HwvtepDeviceInfo(connectionInstance));
166         field(HwvtepConnectionInstance.class, "client").set(connectionInstance, ovsdbClient);
167         when(connectionInstance.getConnectionInfo()).thenReturn(connectionInfo);
168         when(connectionInstance.getConnectionInfo().getRemoteAddress()).thenReturn(mock(InetAddress.class));
169         when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
170         doReturn(listenableDbSchema).when(connectionInstance).getSchema(anyString());
171         when(connectionInstance.getDataBroker()).thenReturn(dataBroker);
172         when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
173         connectionInstance.createTransactInvokers();
174     }
175
176     void mockOperations() {
177         resetOperations();
178     }
179
180     /**
181      * resets the captures so that we can validate the captors of the immediate next execution
182      */
183     void resetOperations() {
184         insertOpCapture = ArgumentCaptor.forClass(TypedBaseTable.class);
185         Update update = mock(Update.class);
186         Insert insert = mock(Insert.class);
187         Delete delete = mock(Delete.class);
188         Where where = mock(Where.class);
189         when(delete.where(any())).thenReturn(where);
190         when(insert.withId(any(String.class))).thenReturn(insert);
191         Operations.op = PowerMockito.mock(Operations.class);
192         when(Operations.op.insert(insertOpCapture.capture())).thenReturn(insert);
193         when(Operations.op.update(insertOpCapture.capture())).thenReturn(update);
194         when(update.where(any())).thenReturn(where);
195         when(Operations.op.delete(any())).thenReturn(delete);
196         ListenableFuture<List<OperationResult>> ft = mock(ListenableFuture.class);
197         transactCaptor = ArgumentCaptor.forClass(List.class);
198         when(ovsdbClient.transact(any(DatabaseSchema.class), transactCaptor.capture())).thenReturn(ft);
199     }
200
201     void addNode(LogicalDatastoreType logicalDatastoreType) throws Exception {
202         NodeBuilder nodeBuilder = prepareNode(nodeIid);
203         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
204         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
205         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
206         transaction.put(logicalDatastoreType, nodeIid, nodeBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
207         transaction.submit();
208     }
209
210     void deleteNode(LogicalDatastoreType logicalDatastoreType) {
211         ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
212         tx.delete(logicalDatastoreType, nodeIid);
213         tx.submit();
214     }
215
216     Node addData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
217                  String[]... data) {
218         NodeBuilder nodeBuilder = prepareNode(nodeIid);
219         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
220         if (LogicalSwitches.class == dataObject) {
221             TestBuilders.addLogicalSwitches(builder, data);
222         }
223         if (TerminationPoint.class == dataObject) {
224             TestBuilders.addGlobalTerminationPoints(nodeBuilder, nodeIid, data);
225         }
226         if (RemoteUcastMacs.class == dataObject) {
227             TestBuilders.addRemoteUcastMacs(nodeIid, builder, data);
228         }
229         if (RemoteMcastMacs.class == dataObject) {
230             TestBuilders.addRemoteMcastMacs(nodeIid, builder, data);
231         }
232         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
233         return mergeNode(logicalDatastoreType, nodeIid, nodeBuilder);
234     }
235
236     void deleteData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
237                  String[]... data) {
238         NodeBuilder nodeBuilder = prepareNode(nodeIid);
239         ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
240         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
241         if (LogicalSwitches.class == dataObject) {
242             List<LogicalSwitches> logicalSwitches = TestBuilders.addLogicalSwitches(builder, data);
243
244             for (LogicalSwitches ls : logicalSwitches) {
245                 InstanceIdentifier<LogicalSwitches> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
246                         child(LogicalSwitches.class, ls.getKey());
247                 tx.delete(logicalDatastoreType, key);
248             }
249         }
250         if (TerminationPoint.class == dataObject) {
251             TestBuilders.addGlobalTerminationPoints(nodeBuilder, nodeIid, data);
252         }
253         if (RemoteUcastMacs.class == dataObject) {
254             List<RemoteUcastMacs> macs = TestBuilders.addRemoteUcastMacs(nodeIid, builder, data);
255             for (RemoteUcastMacs mac : macs) {
256                 InstanceIdentifier<RemoteUcastMacs> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
257                         child(RemoteUcastMacs.class, mac.getKey());
258                 tx.delete(logicalDatastoreType, key);
259             }
260         }
261         if (RemoteMcastMacs.class == dataObject) {
262             List<RemoteMcastMacs> macs = TestBuilders.addRemoteMcastMacs(nodeIid, builder, data);
263             for (RemoteMcastMacs mac : macs) {
264                 InstanceIdentifier<RemoteMcastMacs> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
265                         child(RemoteMcastMacs.class, mac.getKey());
266                 tx.delete(logicalDatastoreType, key);
267             }
268         }
269         tx.submit();
270     }
271
272     NodeBuilder prepareNode(InstanceIdentifier<Node> iid) {
273         NodeBuilder nodeBuilder = new NodeBuilder();
274         nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId());
275         return nodeBuilder;
276     }
277
278     Node mergeNode(LogicalDatastoreType datastoreType, InstanceIdentifier<Node> id, NodeBuilder nodeBuilder) {
279         Node node = nodeBuilder.build();
280         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
281         transaction.merge(datastoreType, id, node, WriteTransaction.CREATE_MISSING_PARENTS);
282         transaction.submit();
283         return node;
284     }
285
286     public InstanceIdentifier<Node> createInstanceIdentifier(String nodeIdString) {
287         NodeId nodeId = new NodeId(new Uri(nodeIdString));
288         NodeKey nodeKey = new NodeKey(nodeId);
289         TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
290         return InstanceIdentifier.builder(NetworkTopology.class)
291                 .child(Topology.class, topoKey)
292                 .child(Node.class, nodeKey)
293                 .build();
294     }
295 }