bug 6579 added dependency queue
[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.Comment;
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.schema.DatabaseSchema;
33 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
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.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.powermock.api.mockito.PowerMockito;
52 import org.powermock.api.support.membermodification.MemberMatcher;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import java.io.InputStream;
57 import java.net.InetAddress;
58 import java.util.List;
59
60 import static org.mockito.Matchers.any;
61 import static org.mockito.Matchers.anyString;
62 import static org.mockito.Mockito.doReturn;
63 import static org.mockito.Mockito.mock;
64 import static org.mockito.Mockito.when;
65 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
66 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
67 import static org.powermock.api.support.membermodification.MemberMatcher.field;
68 import static org.powermock.api.support.membermodification.MemberModifier.suppress;
69
70 public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
71
72     static Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class);
73
74     static DataBroker dataBroker;
75
76     EntityOwnershipService entityOwnershipService;
77     OvsdbClient ovsdbClient;
78     DatabaseSchema dbSchema;
79     ListenableFuture<DatabaseSchema> listenableDbSchema = mock(ListenableFuture.class);
80     TransactionInvoker transactionInvoker;
81     OvsdbConnectionInfo connectionInfo;
82     Operations operations;
83     HwvtepDataChangeListener hwvtepDataChangeListener;
84     HwvtepConnectionManager hwvtepConnectionManager;
85     HwvtepConnectionInstance connectionInstance;
86
87     ArgumentCaptor<TypedBaseTable> insertOpCapture;
88     ArgumentCaptor<List> transactCaptor;
89
90     String nodeUuid;
91     InstanceIdentifier<Node> nodeIid;
92
93     @Before
94     public void setupTest() throws Exception {
95         /**
96          *  Use the same databroker across tests ,otherwise the following exception is thrown
97          *  Caused by: java.lang.RuntimeException: org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.
98          *  topology.rev131021.node.attributes.SupportingNode$StreamWriter: frozen class (cannot edit)
99          */
100         if (dataBroker == null) {
101             dataBroker = super.getDataBroker();
102         }
103         entityOwnershipService = mock(EntityOwnershipService.class);
104         nodeUuid = java.util.UUID.randomUUID().toString();
105         nodeIid = createInstanceIdentifier(nodeUuid);
106         loadSchema();
107         mockConnectionInstance();
108         mockConnectionManager();
109         mockOperations();
110
111         addNode(OPERATIONAL);
112         addNode(CONFIGURATION);
113         hwvtepDataChangeListener = new HwvtepDataChangeListener(dataBroker, hwvtepConnectionManager);
114     }
115
116     @After
117     public void tearDown() throws Exception {
118         hwvtepDataChangeListener.close();
119         deleteNode(OPERATIONAL);
120         deleteNode(CONFIGURATION);
121     }
122
123     void loadSchema() {
124         try (InputStream resourceAsStream = DataChangeListenerTestBase.class.getResourceAsStream("hwvtep_schema.json")) {
125             ObjectMapper mapper = new ObjectMapper();
126             JsonNode jsonNode = mapper.readTree(resourceAsStream);
127             dbSchema = DatabaseSchema.fromJson(HwvtepSchemaConstants.HARDWARE_VTEP,
128                     jsonNode.get("result"));
129             listenableDbSchema = mock(ListenableFuture.class);
130             when(listenableDbSchema.get()).thenReturn(dbSchema);
131         } catch (Exception e) {
132             LOG.error("Failed to load schema", e);
133         }
134     }
135
136     private void mockConnectionManager() throws IllegalAccessException {
137         hwvtepConnectionManager = PowerMockito.mock(HwvtepConnectionManager.class, Mockito.CALLS_REAL_METHODS);
138         field(HwvtepConnectionManager.class, "db").set(hwvtepConnectionManager, dataBroker);
139         field(HwvtepConnectionManager.class, "txInvoker").set(hwvtepConnectionManager, transactionInvoker);
140         field(HwvtepConnectionManager.class, "entityOwnershipService").set(hwvtepConnectionManager, entityOwnershipService);
141         suppress(PowerMockito.method(HwvtepConnectionManager.class, "getConnectionInstance", HwvtepPhysicalSwitchAttributes.class));
142         when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(HwvtepPhysicalSwitchAttributes.class))).
143                 thenReturn(connectionInstance);
144         when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(Node.class))).
145                 thenReturn(connectionInstance);
146     }
147
148     void mockConnectionInstance() throws IllegalAccessException {
149         connectionInfo = mock(OvsdbConnectionInfo.class);
150         ovsdbClient = mock(OvsdbClient.class);
151         transactionInvoker =  new TransactionInvokerImpl(dataBroker);
152
153         connectionInstance = PowerMockito.mock(HwvtepConnectionInstance.class, Mockito.CALLS_REAL_METHODS);
154         field(HwvtepConnectionInstance.class, "instanceIdentifier").set(connectionInstance, nodeIid);
155         field(HwvtepConnectionInstance.class, "txInvoker").set(connectionInstance, transactionInvoker);
156         field(HwvtepConnectionInstance.class, "deviceInfo").set(connectionInstance, new HwvtepDeviceInfo(connectionInstance));
157         field(HwvtepConnectionInstance.class, "client").set(connectionInstance, ovsdbClient);
158         when(connectionInstance.getConnectionInfo()).thenReturn(connectionInfo);
159         when(connectionInstance.getConnectionInfo().getRemoteAddress()).thenReturn(mock(InetAddress.class));
160         when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
161         doReturn(listenableDbSchema).when(connectionInstance).getSchema(anyString());
162         when(connectionInstance.getDataBroker()).thenReturn(dataBroker);
163         when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
164         connectionInstance.createTransactInvokers();
165     }
166
167     void mockOperations() {
168         resetOperations();
169     }
170
171     /**
172      * resets the captures so that we can validate the captors of the immediate next execution
173      */
174     void resetOperations() {
175         insertOpCapture = ArgumentCaptor.forClass(TypedBaseTable.class);
176         Insert insert = mock(Insert.class);
177         when(insert.withId(any(String.class))).thenReturn(insert);
178         Operations.op = PowerMockito.mock(Operations.class);
179         when(Operations.op.comment(any(String.class))).thenReturn(mock(Comment.class));
180         when(Operations.op.insert(insertOpCapture.capture())).thenReturn(insert);
181
182         ListenableFuture<List<OperationResult>> ft = mock(ListenableFuture.class);
183         transactCaptor = ArgumentCaptor.forClass(List.class);
184         when(ovsdbClient.transact(any(DatabaseSchema.class), transactCaptor.capture())).thenReturn(ft);
185     }
186
187     void addNode(LogicalDatastoreType logicalDatastoreType) throws Exception {
188         NodeBuilder nodeBuilder = prepareNode(nodeIid);
189         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
190         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
191         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
192         transaction.put(logicalDatastoreType, nodeIid, nodeBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
193         transaction.submit();
194     }
195
196     void deleteNode(LogicalDatastoreType logicalDatastoreType) {
197         ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
198         tx.delete(logicalDatastoreType, nodeIid);
199         tx.submit();
200     }
201
202     void addData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
203                  String[]... data) {
204         NodeBuilder nodeBuilder = prepareNode(nodeIid);
205         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
206         if (LogicalSwitches.class == dataObject) {
207             TestBuilders.addLogicalSwitches(builder, data);
208         }
209         if (TerminationPoint.class == dataObject) {
210             TestBuilders.addGlobalTerminationPoints(nodeBuilder, nodeIid, data);
211         }
212         if (RemoteUcastMacs.class == dataObject) {
213             TestBuilders.addRemoteUcastMacs(nodeIid, builder, data);
214         }
215         if (RemoteMcastMacs.class == dataObject) {
216             TestBuilders.addRemoteMcastMacs(nodeIid, builder, data);
217         }
218         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
219         mergeNode(logicalDatastoreType, nodeIid, nodeBuilder);
220     }
221
222     NodeBuilder prepareNode(InstanceIdentifier<Node> iid) {
223         NodeBuilder nodeBuilder = new NodeBuilder();
224         nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId());
225         return nodeBuilder;
226     }
227
228     Node mergeNode(LogicalDatastoreType datastoreType, InstanceIdentifier<Node> id, NodeBuilder nodeBuilder) {
229         Node node = nodeBuilder.build();
230         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
231         transaction.merge(datastoreType, id, node, WriteTransaction.CREATE_MISSING_PARENTS);
232         transaction.submit();
233         return node;
234     }
235
236     public InstanceIdentifier<Node> createInstanceIdentifier(String nodeIdString) {
237         NodeId nodeId = new NodeId(new Uri(nodeIdString));
238         NodeKey nodeKey = new NodeKey(nodeId);
239         TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
240         return InstanceIdentifier.builder(NetworkTopology.class)
241                 .child(Topology.class, topoKey)
242                 .child(Node.class, nodeKey)
243                 .build();
244     }
245 }