9f42acfa4ef3756b74bb64e5857a6070dd4baa66
[netvirt.git] / vpnservice / federation-plugin / impl / src / test / java / org / opendaylight / netvirt / federation / plugin / end2end / AbstractEnd2EndTest.java
1 /*
2  * Copyright (c) 2017 Hewlett Packard Enterprise, Co. 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 package org.opendaylight.netvirt.federation.plugin.end2end;
9
10 import static org.mockito.Matchers.any;
11 import static org.mockito.Matchers.anyString;
12 import static org.mockito.Matchers.eq;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.when;
17
18 import com.google.common.base.Optional;
19 import com.google.common.util.concurrent.Futures;
20
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.LinkedList;
26 import java.util.List;
27
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.Mock;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
32 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
33 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
34 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
35 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
36 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
37 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.federation.service.api.IConsumerManagement;
39 import org.opendaylight.federation.service.api.message.WrapperEntityFederationMessage;
40 import org.opendaylight.federation.service.impl.FederationProducerMgr;
41 import org.opendaylight.federation.service.impl.WrapperConsumer;
42 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
43 import org.opendaylight.messagequeue.AbstractFederationMessage;
44 import org.opendaylight.messagequeue.IMessageBusClient;
45 import org.opendaylight.netvirt.elanmanager.api.IElanService;
46 import org.opendaylight.netvirt.federation.plugin.FederatedNetworkPair;
47 import org.opendaylight.netvirt.federation.plugin.FederationPluginEgress;
48 import org.opendaylight.netvirt.federation.plugin.FederationPluginIngress;
49 import org.opendaylight.netvirt.federation.plugin.FederationPluginMgr;
50 import org.opendaylight.netvirt.federation.plugin.FederationPluginUtils;
51 import org.opendaylight.netvirt.federation.plugin.SubnetVpnAssociationManager;
52 import org.opendaylight.netvirt.federation.plugin.creators.FederationElanInterfaceModificationCreator;
53 import org.opendaylight.netvirt.federation.plugin.creators.FederationIetfInterfaceModificationCreator;
54 import org.opendaylight.netvirt.federation.plugin.creators.FederationInventoryNodeModificationCreator;
55 import org.opendaylight.netvirt.federation.plugin.creators.FederationTopologyNodeModificationCreator;
56 import org.opendaylight.netvirt.federation.plugin.creators.FederationVpnInterfaceModificationCreator;
57 import org.opendaylight.netvirt.federation.plugin.filters.FederationElanInterfaceFilter;
58 import org.opendaylight.netvirt.federation.plugin.filters.FederationIetfInterfaceFilter;
59 import org.opendaylight.netvirt.federation.plugin.filters.FederationInventoryNodeFilter;
60 import org.opendaylight.netvirt.federation.plugin.filters.FederationTopologyNodeFilter;
61 import org.opendaylight.netvirt.federation.plugin.filters.FederationVpnInterfaceFilter;
62 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationElanInterfaceIdentifier;
63 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationIetfInterfaceIdentifier;
64 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationInventoryNodeIdentifier;
65 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationTopologyNodeIdentifier;
66 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationVpnInterfaceIdentifier;
67 import org.opendaylight.netvirt.federation.plugin.transformers.FederationElanInterfaceTransformer;
68 import org.opendaylight.netvirt.federation.plugin.transformers.FederationIetfInterfaceTransformer;
69 import org.opendaylight.netvirt.federation.plugin.transformers.FederationInventoryNodeTransformer;
70 import org.opendaylight.netvirt.federation.plugin.transformers.FederationTopologyNodeTransformer;
71 import org.opendaylight.netvirt.federation.plugin.transformers.FederationVpnInterfaceTransformer;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.FederationGenerations;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfo;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfoBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfoKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.federation.service.config.rev161110.FederationConfigData;
77 import org.opendaylight.yangtools.yang.binding.DataObject;
78 import org.opendaylight.yangtools.yang.binding.Identifier;
79 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
80 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
81 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
82
83 public class AbstractEnd2EndTest {
84
85     protected DataBroker dataBroker = mock(DataBroker.class);
86     protected IElanService elanService = mock(IElanService.class);
87     protected SubnetVpnAssociationManager associationMgr = mock(SubnetVpnAssociationManager.class);
88     protected LinkedList<AbstractFederationMessage> sentMessages;
89     public LinkedList<MergedObject> mergedObjects = new LinkedList<>();
90
91     protected FederationProducerMgr producer;
92     protected FederationPluginEgress egressPlugin;
93     protected final HashMap<String, DataTreeChangeListener<?>> keyToListener = new HashMap<>();
94
95     @Mock
96     protected ReadOnlyTransaction mockReadTx;
97
98     protected WriteTransaction stubWriteTx = mock(WriteTransaction.class);
99
100     protected IMessageBusClient msgBusConsumerMock = mock(IMessageBusClient.class);
101
102     protected ClusterSingletonServiceProvider singletonService = mock(ClusterSingletonServiceProvider.class);
103
104     protected IConsumerManagement consumerMgr = mock(IConsumerManagement.class);
105
106     @Mock
107     protected FederationPluginMgr mgr;
108
109     protected FederationPluginIngress ingressPlugin;
110
111     protected WrapperConsumer wrapperConsumer;
112
113     @Mock
114     FederationConfigData configMock;
115
116     @SuppressWarnings("rawtypes")
117     protected HashMap<String, ArgumentCaptor<DataTreeChangeListener>> listenerKeyToCaptor;
118
119     protected final ArgumentCaptor<AbstractFederationMessage> msgCaptor = ArgumentCaptor
120             .forClass(AbstractFederationMessage.class);
121
122     protected static final String REMOTE_IP = "1.1.1.1";
123     protected static final String DUMMYINTERFACE = "dummyinterface";
124     protected static final String REMOTE_TENANT_ID = "remoteTenantId";
125     protected static final String LOCAL_TENANT_ID = "localTenantId";
126     protected static final String PRODUCER_SUBNET_ID = "11112222-ffff-aaaa-2222-333444555666";
127     protected static final String CONSUMER_SUBNET_ID = "11113333-ffff-aaaa-2222-333444555666";
128     protected static final String PRODUCER_NETWORK_ID = "remoteNetworkId";
129     protected static final String CONSUMER_NETWORK_ID = "localNetworkId";
130     protected static final String CONSUMER1_QUEUE = "consumer1Queue";
131     protected static final String CONSUMER2_QUEUE = "consumer2Queue";
132     protected static final String INTEGRATION_BRIDGE_PREFIX = "bridge/br-int";
133
134     public AbstractEnd2EndTest() {
135         FederationInventoryNodeTransformer inventoryNodeTransformer = new FederationInventoryNodeTransformer();
136         new FederationInventoryNodeFilter(dataBroker, inventoryNodeTransformer);
137         new FederationInventoryNodeModificationCreator();
138         new FederationInventoryNodeIdentifier();
139         new FederationTopologyNodeTransformer();
140         new FederationTopologyNodeFilter();
141         new FederationTopologyNodeModificationCreator();
142         new FederationTopologyNodeIdentifier();
143         new FederationIetfInterfaceTransformer();
144         new FederationIetfInterfaceFilter(dataBroker, elanService);
145         new FederationIetfInterfaceModificationCreator();
146         new FederationIetfInterfaceIdentifier();
147         new FederationElanInterfaceTransformer();
148         new FederationElanInterfaceFilter(dataBroker, elanService);
149         new FederationElanInterfaceModificationCreator();
150         new FederationElanInterfaceIdentifier();
151         new FederationVpnInterfaceFilter(dataBroker, associationMgr);
152         new FederationVpnInterfaceTransformer(associationMgr);
153         new FederationVpnInterfaceModificationCreator();
154         new FederationVpnInterfaceIdentifier();
155     }
156
157     public void initialization() {
158         sentMessages = new LinkedList<>();
159         producer = new FederationProducerMgr(msgBusConsumerMock, dataBroker, configMock, singletonService, consumerMgr);
160         producer.attachPluginFactory("netvirt", (payload, queueName, contextId) -> egressPlugin);
161         List<FederatedNetworkPair> federatedNetworkPairs = Arrays.asList(new FederatedNetworkPair(CONSUMER_NETWORK_ID,
162                 PRODUCER_NETWORK_ID, CONSUMER_SUBNET_ID, PRODUCER_SUBNET_ID, LOCAL_TENANT_ID, REMOTE_TENANT_ID));
163         egressPlugin = new FederationPluginEgress(producer, federatedNetworkPairs, CONSUMER1_QUEUE, CONSUMER1_QUEUE);
164         ingressPlugin = new FederationPluginIngress(mgr, dataBroker, REMOTE_IP, federatedNetworkPairs);
165         wrapperConsumer = new WrapperConsumer(REMOTE_IP, ingressPlugin);
166
167         prepareMocks();
168     }
169
170     private void prepareMocks() {
171         HashMap<String, DataTreeIdentifier<?>> listenerKeyToIdentifer = new HashMap<>();
172         listenerKeyToCaptor = new HashMap<>();
173         egressPlugin.getListenersData().forEach(p -> listenerKeyToIdentifer.put(p.listenerId, p.listenerPath));
174         egressPlugin.getListenersData().forEach(
175             p -> listenerKeyToCaptor.put(p.listenerId, ArgumentCaptor.forClass(DataTreeChangeListener.class)));
176         for (String key : FederationPluginUtils.getOrderedListenerKeys()) {
177             when(dataBroker.registerDataTreeChangeListener(eq(listenerKeyToIdentifer.get(key)),
178                     listenerKeyToCaptor.get(key).capture())).thenReturn(null);
179         }
180
181         doAnswer(invocation -> {
182             AbstractFederationMessage msg = (AbstractFederationMessage) invocation.getArguments()[0];
183             sentMessages.add(msg);
184             wrapperConsumer.consumeMsg(msg);
185             return null;
186         }).when(msgBusConsumerMock).sendMsg(any(), anyString());
187
188         doReturn("2.2.2.2").when(configMock).getMqBrokerIp();
189         doReturn(stubWriteTx).when(dataBroker).newWriteOnlyTransaction();
190         when(associationMgr.getSubnetVpn(any())).thenReturn("dummySubnetVpn");
191         doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
192
193         when(stubWriteTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
194         doAnswer(invocation -> {
195             InstanceIdentifier<?> path = (InstanceIdentifier<?>) invocation.getArguments()[1];
196             DataObject data = (DataObject) invocation.getArguments()[2];
197             mergedObjects.add(new MergedObject(data, path));
198             return null;
199         }).when(stubWriteTx).merge(any(), any(), any());
200     }
201
202     protected class MergedObject {
203         public DataObject obj;
204         public InstanceIdentifier<?> insId;
205
206         public MergedObject(DataObject obj, InstanceIdentifier<?> insId) {
207             this.obj = obj;
208             this.insId = insId;
209         }
210     }
211
212     public int mergedObjectsAmount() {
213         return mergedObjects.size();
214     }
215
216     protected <T extends DataObject> T removeLastMerged(Class<T> type) {
217         return type.cast(mergedObjects.removeLast().obj);
218     }
219
220     protected <T extends DataObject> T removeFirstMerged(Class<T> type) {
221         return type.cast(mergedObjects.removeFirst().obj);
222     }
223
224     protected String lastSentJson() {
225         AbstractFederationMessage lastMsg = sentMessages.getLast();
226         WrapperEntityFederationMessage wrapper = (WrapperEntityFederationMessage) lastMsg;
227         return wrapper.getPayload().getJsonInput();
228     }
229
230     @SuppressWarnings({ "unchecked", "rawtypes" })
231     protected void dcn(String listenerKey, DataObject newObject) {
232         DataTreeChangeListener listener = getListenerForKey(listenerKey);
233         listener.onDataTreeChanged(change(newObject, FederationPluginUtils.getListenerDatastoreType(listenerKey),
234                 FederationPluginUtils.getInstanceIdentifier(listenerKey)));
235     }
236
237     @SuppressWarnings({ "rawtypes", "unchecked" })
238     protected void dcns(String listenerKey, List<? extends DataObject> newObjects) {
239         DataTreeChangeListener listener = getListenerForKey(listenerKey);
240         listener.onDataTreeChanged(changes(FederationPluginUtils.getListenerDatastoreType(listenerKey),
241                 FederationPluginUtils.getInstanceIdentifier(listenerKey), newObjects));
242     }
243
244     protected DataTreeChangeListener<?> getListenerForKey(String listenerKey) {
245         return listenerKeyToCaptor.get(listenerKey).getValue();
246     }
247
248     protected Collection<DataTreeModification<?>> changes(LogicalDatastoreType datastoreType,
249             InstanceIdentifier<? extends DataObject> instanceIdentifier, List<? extends DataObject> dataObjects) {
250         ArrayList<DataTreeModification<?>> changes = new ArrayList<>();
251         dataObjects.forEach(data -> changes.add(new FakeDataTreeModification(data, datastoreType, instanceIdentifier)));
252         return changes;
253     }
254
255     protected Collection<?> change(DataObject newObject, LogicalDatastoreType datastoreType,
256             InstanceIdentifier<? extends DataObject> instanceIdentifier) {
257         ArrayList<DataTreeModification<?>> changes = new ArrayList<>();
258         changes.add(new FakeDataTreeModification(newObject, datastoreType, instanceIdentifier));
259         return changes;
260     }
261
262     protected void setGenerationNumberMock() {
263         int generationNumberValue = 2;
264         KeyedInstanceIdentifier<RemoteSiteGenerationInfo, RemoteSiteGenerationInfoKey>
265             generationNumberPath = InstanceIdentifier.create(FederationGenerations.class)
266                 .child(RemoteSiteGenerationInfo.class, new RemoteSiteGenerationInfoKey(REMOTE_IP));
267         RemoteSiteGenerationInfo generationNumber = new RemoteSiteGenerationInfoBuilder().setRemoteIp(REMOTE_IP)
268                 .setGenerationNumber(generationNumberValue).build();
269         when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, generationNumberPath))
270                 .thenReturn(Futures.immediateCheckedFuture(Optional.of(generationNumber)));
271     }
272
273     @SuppressWarnings("rawtypes")
274     public class FakeDataTreeModification implements DataTreeModification {
275
276         private final FakeDataObjectModification fakeMod;
277         private final LogicalDatastoreType dataStoreType;
278         private final InstanceIdentifier<? extends DataObject> instanceIdentifier;
279
280         public FakeDataTreeModification(DataObject theObject, LogicalDatastoreType datastoreType,
281                 InstanceIdentifier<? extends DataObject> instanceIdentifier) {
282             fakeMod = new FakeDataObjectModification(theObject);
283             this.dataStoreType = datastoreType;
284             this.instanceIdentifier = instanceIdentifier;
285         }
286
287         @SuppressWarnings("unchecked")
288         @Override
289         public DataTreeIdentifier<?> getRootPath() {
290             return new DataTreeIdentifier(dataStoreType, instanceIdentifier);
291         }
292
293         @Override
294         public DataObjectModification<?> getRootNode() {
295             return fakeMod;
296         }
297
298     }
299
300     @SuppressWarnings("rawtypes")
301     public class FakeDataObjectModification implements DataObjectModification {
302
303         private final DataObject theObject;
304
305         private final ModificationType modType = ModificationType.WRITE;
306
307         public FakeDataObjectModification(DataObject theObject) {
308             this.theObject = theObject;
309         }
310
311         @Override
312         public PathArgument getIdentifier() {
313             return null;
314         }
315
316         @Override
317         public Class getDataType() {
318             return null;
319         }
320
321         @Override
322         public ModificationType getModificationType() {
323             return modType;
324         }
325
326         @Override
327         public DataObject getDataBefore() {
328             return null;
329         }
330
331         @Override
332         public DataObject getDataAfter() {
333             return theObject;
334         }
335
336         @Override
337         public Collection<?> getModifiedChildren() {
338             return null;
339         }
340
341         @Override
342         public DataObjectModification<?> getModifiedChildContainer(Class child) {
343             return null;
344         }
345
346         @Override
347         public DataObjectModification<?> getModifiedAugmentation(Class augmentation) {
348             return null;
349         }
350
351         @Override
352         public DataObjectModification<?> getModifiedChildListItem(Class listItem, Identifier listKey) {
353             return null;
354         }
355
356         @Override
357         public DataObjectModification<?> getModifiedChild(PathArgument childArgument) {
358             return null;
359         }
360
361     }
362 }