BUG-2383 : Application peer rework.
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / controller / config / yang / bgp / rib / impl / AbstractRIBImplModuleTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.config.yang.bgp.rib.impl;
9
10 import static org.mockito.Matchers.any;
11 import static org.mockito.Mockito.mock;
12
13 import com.google.common.base.Optional;
14 import com.google.common.collect.Lists;
15 import com.google.common.io.ByteSource;
16 import com.google.common.io.Resources;
17 import com.google.common.util.concurrent.CheckedFuture;
18 import java.io.IOException;
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Modifier;
21 import java.net.URL;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Dictionary;
26 import java.util.List;
27 import javax.management.InstanceAlreadyExistsException;
28 import javax.management.InstanceNotFoundException;
29 import javax.management.ObjectName;
30 import org.junit.After;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.mockito.Matchers;
34 import org.mockito.Mock;
35 import org.mockito.Mockito;
36 import org.mockito.MockitoAnnotations;
37 import org.opendaylight.controller.config.api.jmx.CommitStatus;
38 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
39 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
40 import org.opendaylight.controller.config.spi.ModuleFactory;
41 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
42 import org.opendaylight.controller.config.yang.bgp.parser.spi.SimpleBGPExtensionProviderContextModuleFactory;
43 import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModuleFactory;
44 import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModuleMXBean;
45 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleFactory;
46 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleMXBean;
47 import org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModuleFactory;
48 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleFactory;
49 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleFactory;
50 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleMXBean;
51 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleFactory;
52 import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
53 import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
54 import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
55 import org.opendaylight.controller.config.yang.protocol.framework.TimedReconnectStrategyFactoryModuleFactory;
56 import org.opendaylight.controller.config.yang.protocol.framework.TimedReconnectStrategyModuleTest;
57 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
58 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
59 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
60 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
61 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
62 import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
65 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
66 import org.opendaylight.yangtools.yang.binding.DataObject;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.RpcResult;
69 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
70 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
71 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
72 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
73 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
74 import org.opendaylight.yangtools.yang.parser.repo.URLSchemaContextResolver;
75 import org.osgi.framework.Bundle;
76 import org.osgi.framework.BundleListener;
77 import org.osgi.framework.Filter;
78 import org.osgi.framework.ServiceListener;
79 import org.osgi.framework.ServiceReference;
80
81 public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
82
83     private static final String INSTANCE_NAME = "rib-impl";
84     private static final String FACTORY_NAME = RIBImplModuleFactory.NAME;
85     private static final String TRANSACTION_NAME = "testTransaction";
86
87     protected static final RibId RIB_ID = new RibId("test");
88     protected static final Ipv4Address BGP_ID = new Ipv4Address("192.168.1.1");
89     protected static final Ipv4Address CLUSTER_ID = new Ipv4Address("192.168.1.2");
90
91     private static final String SESSION_RS_INSTANCE_NAME = "session-reconnect-strategy-factory";
92     private static final String TCP_RS_INSTANCE_NAME = "tcp-reconnect-strategy-factory";
93     private static final String RIB_EXTENSIONS_INSTANCE_NAME = "rib-extensions-impl";
94     private static final String DOM_BROKER_INSTANCE_NAME = "dom-broker-impl";
95     private static final String BINDING_ASYNC_BROKER_INSTANCE_NAME = "binding-async-broker-instance";
96     private static final String DOM_ASYNC_DATA_BROKER_INSTANCE = "dom-inmemory-data-broker";
97
98     @Mock
99     private ReadWriteTransaction mockedTransaction;
100
101     @Mock
102     private DataBroker mockedDataProvider;
103
104     @Mock
105     private CheckedFuture<Void, TransactionCommitFailedException> mockedFuture;
106
107     @Mock
108     private RpcResult<TransactionStatus> mockedResult;
109
110     @SuppressWarnings("unchecked")
111     @Before
112     public void setUp() throws Exception {
113         MockitoAnnotations.initMocks(this);
114
115         final List<ModuleFactory> moduleFactories = getModuleFactories();
116         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.mockedContext, moduleFactories.toArray(new ModuleFactory[moduleFactories.size()])));
117
118         final Filter mockedFilter = mock(Filter.class);
119         Mockito.doReturn(mockedFilter).when(this.mockedContext).createFilter(Mockito.anyString());
120
121         final ServiceReference<?> emptyServiceReference = mock(ServiceReference.class, "Empty");
122         final ServiceReference<?> classLoadingStrategySR = mock(ServiceReference.class, "ClassLoadingStrategy");
123         final ServiceReference<?> dataProviderServiceReference = mock(ServiceReference.class, "Data Provider");
124
125         Mockito.doReturn(mockedFilter).when(this.mockedContext).createFilter(Mockito.anyString());
126
127         Mockito.doNothing().when(this.mockedContext).addServiceListener(any(ServiceListener.class), Mockito.anyString());
128         Mockito.doNothing().when(this.mockedContext).removeServiceListener(any(ServiceListener.class));
129
130         Mockito.doNothing().when(this.mockedContext).addBundleListener(any(BundleListener.class));
131         Mockito.doNothing().when(this.mockedContext).removeBundleListener(any(BundleListener.class));
132
133         Mockito.doReturn(new Bundle[] {}).when(this.mockedContext).getBundles();
134
135         Mockito.doReturn(new ServiceReference[] {}).when(this.mockedContext).getServiceReferences(Matchers.anyString(), Matchers.anyString());
136
137         Mockito.doReturn("Empty reference").when(emptyServiceReference).toString();
138         Mockito.doReturn("Data Provider Service Reference").when(dataProviderServiceReference).toString();
139         Mockito.doReturn("Class loading stategy reference").when(classLoadingStrategySR).toString();
140
141         Mockito.doReturn(emptyServiceReference).when(this.mockedContext).getServiceReference(any(Class.class));
142         Mockito.doReturn(dataProviderServiceReference).when(this.mockedContext).getServiceReference(DataBroker.class);
143         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(GeneratedClassLoadingStrategy.class);
144
145         Mockito.doReturn(this.mockedDataProvider).when(this.mockedContext).getService(dataProviderServiceReference);
146         Mockito.doReturn(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()).when(this.mockedContext).getService(classLoadingStrategySR);
147         Mockito.doReturn(null).when(this.mockedContext).getService(emptyServiceReference);
148
149         Mockito.doReturn(this.mockedTransaction).when(this.mockedDataProvider).newReadWriteTransaction();
150
151         Mockito.doReturn(null).when(this.mockedTransaction).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
152         Mockito.doNothing().when(this.mockedTransaction).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), any(DataObject.class));
153         Mockito.doNothing().when(this.mockedTransaction).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
154
155         Mockito.doReturn(this.mockedFuture).when(this.mockedTransaction).submit();
156         Mockito.doReturn(TRANSACTION_NAME).when(this.mockedTransaction).getIdentifier();
157
158         Mockito.doReturn(null).when(this.mockedFuture).get();
159
160         final GlobalBundleScanningSchemaServiceImpl schemaService = GlobalBundleScanningSchemaServiceImpl.createInstance(this.mockedContext);
161         final YangContextParser parser = new YangParserImpl();
162         final SchemaContext context = parser.parseSources(getFilesAsByteSources(getYangModelsPaths()));
163         final URLSchemaContextResolver mockedContextResolver = Mockito.mock(URLSchemaContextResolver.class);
164         Mockito.doReturn(Optional.of(context)).when(mockedContextResolver).getSchemaContext();
165
166         final Field contextResolverField = schemaService.getClass().getDeclaredField("contextResolver");
167         contextResolverField.setAccessible(true);
168
169         final Field modifiersField = Field.class.getDeclaredField("modifiers");
170         modifiersField.setAccessible(true);
171         modifiersField.setInt(contextResolverField, contextResolverField.getModifiers() & ~Modifier.FINAL);
172
173         contextResolverField.set(schemaService, mockedContextResolver);
174     }
175
176     protected List<ModuleFactory> getModuleFactories() {
177         return Lists.newArrayList(new RIBImplModuleFactory(), new GlobalEventExecutorModuleFactory(),
178                 new BGPDispatcherImplModuleFactory(), new NettyThreadgroupModuleFactory(),
179                 new TimedReconnectStrategyFactoryModuleFactory(), new SimpleBGPExtensionProviderContextModuleFactory(),
180                 new RIBExtensionsImplModuleFactory(), new DomBrokerImplModuleFactory(), new RuntimeMappingModuleFactory(),
181                 new HashedWheelTimerModuleFactory(), new BindingAsyncDataBrokerImplModuleFactory(),
182                 new DomInmemoryDataBrokerModuleFactory(), new SchemaServiceImplSingletonModuleFactory());
183     }
184
185     @Override
186     protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(final Class<?> serviceType) {
187         if (serviceType.equals(SchemaContextListener.class)) {
188             return new BundleContextServiceRegistrationHandler() {
189                 @Override
190                 public void handleServiceRegistration(final Class<?> clazz, final Object serviceInstance, final Dictionary<String, ?> props) {
191                     final SchemaContextListener listener = (SchemaContextListener) serviceInstance;
192                     final YangContextParser parser = new YangParserImpl();
193                     final SchemaContext context;
194                     try {
195                         context = parser.parseSources(getFilesAsByteSources(getYangModelsPaths()));
196                     } catch (IOException | YangSyntaxErrorException e) {
197                         throw new IllegalStateException("Failed to parse models", e);
198                     }
199                     listener.onGlobalContextUpdated(context);
200                 }
201             };
202         }
203
204         return super.getBundleContextServiceRegistrationHandler(serviceType);
205     }
206
207     @After
208     public void closeAllModules() throws Exception {
209         super.destroyAllConfigBeans();
210         GlobalBundleScanningSchemaServiceImpl.destroyInstance();
211
212     }
213
214     protected CommitStatus createInstance() throws Exception {
215         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
216         createRIBImplModuleInstance(transaction);
217         return transaction.commit();
218     }
219
220     protected CommitStatus createRIBImplModuleInstance(final RibId ribId, final Long localAs, final Ipv4Address bgpId, final Ipv4Address clusterId) throws Exception {
221         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
222         createRIBImplModuleInstance(transaction, ribId, localAs, bgpId, clusterId, createAsyncDataBrokerInstance(transaction));
223         return transaction.commit();
224     }
225
226     private ObjectName createRIBImplModuleInstance(final ConfigTransactionJMXClient transaction, final RibId ribId, final Long localAs,
227             final Ipv4Address bgpId, final Ipv4Address clusterId, final ObjectName dataBroker) throws Exception {
228         final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
229         final RIBImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, RIBImplModuleMXBean.class);
230         final ObjectName reconnectObjectName = TimedReconnectStrategyModuleTest.createInstance(transaction, SESSION_RS_INSTANCE_NAME);
231         mxBean.setSessionReconnectStrategy(reconnectObjectName);
232         mxBean.setDataProvider(dataBroker);
233         mxBean.setDomDataProvider(lookupDomAsyncDataBroker(transaction));
234         mxBean.setCodecTreeFactory(lookupMappingServiceInstance(transaction));
235         final ObjectName reconnectStrategyON = TimedReconnectStrategyModuleTest.createInstance(transaction, TCP_RS_INSTANCE_NAME);
236         mxBean.setTcpReconnectStrategy(reconnectStrategyON);
237         mxBean.setBgpDispatcher(BGPDispatcherImplModuleTest.createInstance(transaction));
238         mxBean.setExtensions(createRibExtensionsInstance(transaction));
239         mxBean.setRibId(ribId);
240         mxBean.setLocalAs(localAs);
241         mxBean.setBgpRibId(bgpId);
242         mxBean.setClusterId(clusterId);
243         return nameCreated;
244     }
245
246     protected ObjectName createRIBImplModuleInstance(final ConfigTransactionJMXClient transaction) throws Exception {
247         return createRIBImplModuleInstance(transaction, RIB_ID, 5000L, BGP_ID, CLUSTER_ID,
248                 createAsyncDataBrokerInstance(transaction));
249     }
250
251     public ObjectName createRIBImplModuleInstance(final ConfigTransactionJMXClient transaction, final ObjectName dataBroker)
252             throws Exception {
253         return createRIBImplModuleInstance(transaction, RIB_ID, 5000L, BGP_ID, CLUSTER_ID, dataBroker);
254     }
255
256     public ObjectName createAsyncDataBrokerInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException, InstanceNotFoundException {
257         final ObjectName nameCreated = transaction.createModule(BindingAsyncDataBrokerImplModuleFactory.NAME, BINDING_ASYNC_BROKER_INSTANCE_NAME);
258         final BindingAsyncDataBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, BindingAsyncDataBrokerImplModuleMXBean.class);
259         mxBean.setBindingMappingService(lookupMappingServiceInstance(transaction));
260         mxBean.setDomAsyncBroker(lookupDomAsyncDataBroker(transaction));
261         mxBean.setSchemaService(lookupSchemaServiceInstance(transaction));
262         return nameCreated;
263     }
264
265     public static ObjectName lookupDomAsyncDataBroker(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
266         try {
267             return transaction.lookupConfigBean(DomInmemoryDataBrokerModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
268         } catch (final InstanceNotFoundException e) {
269             try {
270                 final ObjectName nameCreated = transaction.createModule(DomInmemoryDataBrokerModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
271                 final DomInmemoryDataBrokerModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, DomInmemoryDataBrokerModuleMXBean.class);
272                 mxBean.setSchemaService(lookupSchemaServiceInstance(transaction));
273                 return nameCreated;
274             } catch (final InstanceAlreadyExistsException e1) {
275                 throw new IllegalStateException(e1);
276             }
277         }
278     }
279
280     private static ObjectName lookupMappingServiceInstance(final ConfigTransactionJMXClient transaction) {
281         try {
282             return transaction.lookupConfigBean(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
283         } catch (final InstanceNotFoundException e) {
284             try {
285                 return transaction.createModule(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
286             } catch (final InstanceAlreadyExistsException e1) {
287                 throw new IllegalStateException(e1);
288             }
289         }
290     }
291
292     private static ObjectName lookupSchemaServiceInstance(final ConfigTransactionJMXClient transaction) {
293         try {
294             return transaction.lookupConfigBean(SchemaServiceImplSingletonModuleFactory.NAME, SchemaServiceImplSingletonModuleFactory.SINGLETON_NAME);
295         } catch (final InstanceNotFoundException e) {
296             try {
297                 return transaction.createModule(SchemaServiceImplSingletonModuleFactory.NAME, SchemaServiceImplSingletonModuleFactory.SINGLETON_NAME);
298             } catch (final InstanceAlreadyExistsException e1) {
299                 throw new IllegalStateException(e1);
300             }
301         }
302     }
303
304     private ObjectName createRibExtensionsInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
305         final ObjectName nameCreated = transaction.createModule(RIBExtensionsImplModuleFactory.NAME, RIB_EXTENSIONS_INSTANCE_NAME);
306         transaction.newMXBeanProxy(nameCreated, RIBExtensionsImplModuleMXBean.class);
307         return nameCreated;
308     }
309
310     public List<String> getYangModelsPaths() {
311         final List<String> paths = Lists.newArrayList("/META-INF/yang/bgp-rib.yang", "/META-INF/yang/ietf-inet-types.yang",
312                 "/META-INF/yang/bgp-message.yang", "/META-INF/yang/bgp-multiprotocol.yang", "/META-INF/yang/bgp-types.yang",
313                 "/META-INF/yang/network-concepts.yang", "/META-INF/yang/ieee754.yang");
314         return paths;
315     }
316
317     // TODO move back to AbstractConfigTest
318     private static Collection<ByteSource> getFilesAsByteSources(final List<String> paths) {
319         final Collection<ByteSource> resources = new ArrayList<>();
320         final List<String> failedToFind = new ArrayList<>();
321         for (final String path : paths) {
322             final URL url = AbstractRIBImplModuleTest.class.getResource(path);
323             if (url == null) {
324                 failedToFind.add(path);
325             } else {
326                 resources.add(Resources.asByteSource(url));
327             }
328         }
329         Assert.assertEquals("Some files were not found", Collections.<String> emptyList(), failedToFind);
330
331         return resources;
332     }
333 }