a9f1595f28baf1c5f4d53ba7c8a0affedddd2b8d
[bgpcep.git] / bgp / bmp-impl / src / test / java / org / opendaylight / controller / config / yang / bmp / impl / BmpMonitorImplModuleTest.java
1 /*
2  * Copyright (c) 2015 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.bmp.impl;
9
10 import static org.mockito.Matchers.any;
11 import static org.mockito.Matchers.anyString;
12 import static org.mockito.Matchers.contains;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import com.google.common.collect.Lists;
18 import com.google.common.io.ByteSource;
19 import com.google.common.io.Resources;
20 import com.google.common.util.concurrent.CheckedFuture;
21 import io.netty.channel.EventLoopGroup;
22 import io.netty.util.concurrent.EventExecutor;
23 import java.io.IOException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
29 import javax.management.InstanceAlreadyExistsException;
30 import javax.management.ObjectName;
31 import org.junit.After;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.mockito.Matchers;
36 import org.mockito.Mock;
37 import org.mockito.Mockito;
38 import org.mockito.MockitoAnnotations;
39 import org.mockito.invocation.InvocationOnMock;
40 import org.mockito.stubbing.Answer;
41 import org.opendaylight.controller.config.api.jmx.CommitStatus;
42 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
43 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
44 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
45 import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModuleFactory;
46 import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModuleMXBean;
47 import org.opendaylight.controller.config.yang.bmp.spi.SimpleBmpExtensionProviderContextModuleFactory;
48 import org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModuleFactory;
49 import org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModuleMXBean;
50 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleFactory;
51 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleMXBean;
52 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleFactory;
53 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleMXBean;
54 import org.opendaylight.controller.config.yang.netty.eventexecutor.AutoCloseableEventExecutor;
55 import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
56 import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
57 import org.opendaylight.controller.config.yang.netty.threadgroup.NioEventLoopGroupCloseable;
58 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
59 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
60 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory;
61 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
62 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
63 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
64 import org.opendaylight.controller.sal.core.api.model.SchemaService;
65 import org.opendaylight.controller.sal.core.api.model.YangTextSourceProvider;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
67 import org.opendaylight.yangtools.concepts.ListenerRegistration;
68 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
69 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
70 import org.opendaylight.yangtools.yang.binding.DataObject;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.opendaylight.yangtools.yang.common.RpcResult;
73 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
74 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
75 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
76 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
77 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
78 import org.osgi.framework.Bundle;
79 import org.osgi.framework.BundleListener;
80 import org.osgi.framework.Filter;
81 import org.osgi.framework.ServiceListener;
82 import org.osgi.framework.ServiceReference;
83
84 public class BmpMonitorImplModuleTest extends AbstractConfigTest {
85
86     private static final String FACTORY_NAME = BmpMonitorImplModuleFactory.NAME;
87     private static final String INSTANCE_NAME = "bmp-monitor-impl-instance";
88     private static final String RIB_EXT_INSTANCE_NAME = "rib-ext-instance";
89     private static final String CODEC_INSTANCE_NAME = "runtime-mapping-singleton";
90     private static final String DOM_INSTANCE_NAME = "dom-data-instance";
91     private static final String TRANSACTION_NAME = "testTransaction";
92
93     @Mock private ReadWriteTransaction mockedTransaction;
94     @Mock private DataBroker mockedDataProvider;
95     @Mock private CheckedFuture<Void, TransactionCommitFailedException> mockedFuture;
96     @Mock private RpcResult<TransactionStatus> mockedResult;
97
98     @SuppressWarnings("unchecked")
99     @Before
100     public void setUp() throws Exception {
101         MockitoAnnotations.initMocks(this);
102
103         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.mockedContext,
104             new BmpMonitorImplModuleFactory(),
105             new RIBExtensionsImplModuleFactory(),
106             new RuntimeMappingModuleFactory(),
107             new DomInmemoryDataBrokerModuleFactory(),
108             new BmpDispatcherImplModuleFactory(),
109             new NettyThreadgroupModuleFactory(),
110             new SimpleBmpExtensionProviderContextModuleFactory(),
111             new GlobalEventExecutorModuleFactory(),
112             new SchemaServiceImplSingletonModuleFactory()));
113
114         doAnswer(new Answer<Filter>() {
115             @Override
116             public Filter answer(final InvocationOnMock invocation) {
117                 final String str = invocation.getArgumentAt(0, String.class);
118                 final Filter mockFilter = mock(Filter.class);
119                 doReturn(str).when(mockFilter).toString();
120                 return mockFilter;
121             }
122         }).when(mockedContext).createFilter(anyString());
123
124         final ServiceReference<?> emptyServiceReference = mock(ServiceReference.class, "Empty");
125         final ServiceReference<?> classLoadingStrategySR = mock(ServiceReference.class, "ClassLoadingStrategy");
126         final ServiceReference<?> dataProviderServiceReference = mock(ServiceReference.class, "Data Provider");
127         final ServiceReference<?> schemaServiceReference = mock(ServiceReference.class, "schemaServiceReference");
128
129         Mockito.doNothing().when(this.mockedContext).addServiceListener(any(ServiceListener.class), Mockito.anyString());
130         Mockito.doNothing().when(this.mockedContext).removeServiceListener(any(ServiceListener.class));
131
132         Mockito.doNothing().when(this.mockedContext).addBundleListener(any(BundleListener.class));
133         Mockito.doNothing().when(this.mockedContext).removeBundleListener(any(BundleListener.class));
134
135         Mockito.doReturn(new Bundle[] {}).when(this.mockedContext).getBundles();
136
137         Mockito.doReturn(new ServiceReference[] {}).when(this.mockedContext).getServiceReferences(Matchers.anyString(), Matchers.anyString());
138
139         Mockito.doReturn("Empty reference").when(emptyServiceReference).toString();
140         Mockito.doReturn("Data Provider Service Reference").when(dataProviderServiceReference).toString();
141         Mockito.doReturn("Class loading stategy reference").when(classLoadingStrategySR).toString();
142         Mockito.doReturn("Schema Service reference").when(schemaServiceReference).toString();
143
144         Mockito.doReturn(emptyServiceReference).when(this.mockedContext).getServiceReference(any(Class.class));
145         Mockito.doReturn(dataProviderServiceReference).when(this.mockedContext).getServiceReference(DataBroker.class);
146         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(GeneratedClassLoadingStrategy.class);
147         Mockito.doReturn(schemaServiceReference).when(this.mockedContext).getServiceReference(SchemaService.class);
148         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(ClassLoadingStrategy.class);
149
150         Mockito.doReturn(this.mockedDataProvider).when(this.mockedContext).getService(dataProviderServiceReference);
151         Mockito.doReturn(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()).when(this.mockedContext).getService(classLoadingStrategySR);
152         Mockito.doReturn(null).when(this.mockedContext).getService(emptyServiceReference);
153
154         Mockito.doReturn(this.mockedTransaction).when(this.mockedDataProvider).newReadWriteTransaction();
155
156         Mockito.doReturn(null).when(this.mockedTransaction).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
157         Mockito.doNothing().when(this.mockedTransaction).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), any(DataObject.class));
158         Mockito.doNothing().when(this.mockedTransaction).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
159
160         Mockito.doReturn(this.mockedFuture).when(this.mockedTransaction).submit();
161         Mockito.doReturn(TRANSACTION_NAME).when(this.mockedTransaction).getIdentifier();
162
163         Mockito.doReturn(null).when(this.mockedFuture).get();
164
165         final SchemaContext context = parseYangStreams(getFilesAsByteSources(getYangModelsPaths()));
166         final SchemaService mockedSchemaService = mock(SchemaService.class);
167         doReturn(context).when(mockedSchemaService).getGlobalContext();
168         doAnswer(new Answer<ListenerRegistration<SchemaContextListener>>() {
169             @Override
170             public ListenerRegistration<SchemaContextListener> answer(InvocationOnMock invocation) {
171                 invocation.getArgumentAt(0, SchemaContextListener.class).onGlobalContextUpdated(context);
172                 ListenerRegistration<SchemaContextListener> reg = mock(ListenerRegistration.class);
173                 doNothing().when(reg).close();
174                 return reg;
175             }
176         }).when(mockedSchemaService).registerSchemaContextListener(any(SchemaContextListener.class));
177
178         setupMockService(SchemaService.class, mockedSchemaService);
179         setupMockService(YangTextSourceProvider.class, mock(YangTextSourceProvider.class));
180         Mockito.doReturn(mockedSchemaService).when(this.mockedContext).getService(schemaServiceReference);
181
182         BindingToNormalizedNodeCodecFactory.getOrCreateInstance(
183                 GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), mockedSchemaService);
184
185         setupMockService(EventLoopGroup.class, NioEventLoopGroupCloseable.newInstance(0));
186         setupMockService(EventExecutor.class, AutoCloseableEventExecutor.CloseableEventExecutorMixin.globalEventExecutor());
187     }
188
189     private void setupMockService(final Class<?> serviceInterface, final Object instance) throws Exception {
190         final ServiceReference<?> mockServiceRef = mock(ServiceReference.class);
191         doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext).
192                 getServiceReferences(anyString(), contains(serviceInterface.getName()));
193         doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext).
194                 getServiceReferences(serviceInterface.getName(), null);
195         doReturn(instance).when(mockedContext).getService(mockServiceRef);
196     }
197
198     private static SchemaContext parseYangStreams(final Collection<ByteSource> streams) {
199         final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
200         try {
201             return reactor.buildEffective(streams);
202         } catch (final ReactorException | IOException e) {
203             throw new RuntimeException("Unable to build schema context from " + streams, e);
204         }
205     }
206
207     private List<String> getYangModelsPaths() {
208         final List<String> paths = Lists.newArrayList("/META-INF/yang/bgp-rib.yang", "/META-INF/yang/ietf-inet-types.yang",
209                 "/META-INF/yang/bgp-message.yang", "/META-INF/yang/bgp-multiprotocol.yang", "/META-INF/yang/bgp-types.yang",
210                 "/META-INF/yang/network-concepts.yang", "/META-INF/yang/ieee754.yang", "/META-INF/yang/yang-ext.yang",
211                 "/META-INF/yang/bmp-monitor.yang", "/META-INF/yang/bmp-message.yang", "/META-INF/yang/ietf-yang-types.yang");
212         return paths;
213     }
214
215     private Collection<ByteSource> getFilesAsByteSources(final List<String> paths) {
216         final Collection<ByteSource> resources = new ArrayList<>();
217         final List<String> failedToFind = new ArrayList<>();
218         for (final String path : paths) {
219             final URL url = BmpMonitorImplModuleTest.class.getResource(path);
220             if (url == null) {
221                 failedToFind.add(path);
222             } else {
223                 resources.add(Resources.asByteSource(url));
224             }
225         }
226         Assert.assertEquals("Some files were not found", Collections.<String> emptyList(), failedToFind);
227         return resources;
228     }
229
230     @After
231     public void closeAllModules() throws Exception {
232         super.destroyAllConfigBeans();
233     }
234
235     @Test
236     public void testCreateBean() throws Exception {
237         final CommitStatus status = createInstance();
238         assertBeanCount(1, FACTORY_NAME);
239         assertStatus(status, 9, 0, 0);
240     }
241
242     @Test
243     public void testReusingOldInstance() throws Exception {
244         createInstance();
245         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
246         assertBeanCount(1, FACTORY_NAME);
247         final CommitStatus status = transaction.commit();
248         assertBeanCount(1, FACTORY_NAME);
249         assertStatus(status, 0, 0, 9);
250     }
251
252     private CommitStatus createInstance() throws Exception {
253         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
254         final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
255         final BmpMonitorImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, BmpMonitorImplModuleMXBean.class);
256         mxBean.setExtensions(createExtensions(transaction));
257         mxBean.setCodecTreeFactory(createRuntimeMapping(transaction));
258         mxBean.setDomDataProvider(createDomData(transaction));
259         mxBean.setBmpDispatcher(createDispatcher(transaction));
260         mxBean.setBindingPort(new PortNumber(9999));
261         return transaction.commit();
262     }
263
264     private static ObjectName createExtensions(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
265         final ObjectName nameCreated = transaction.createModule(RIBExtensionsImplModuleFactory.NAME, RIB_EXT_INSTANCE_NAME);
266         transaction.newMXBeanProxy(nameCreated, RIBExtensionsImplModuleMXBean.class);
267         return nameCreated;
268     }
269
270     private static ObjectName createRuntimeMapping(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
271         final ObjectName nameCreated = transaction.createModule(RuntimeMappingModuleFactory.NAME, CODEC_INSTANCE_NAME);
272         transaction.newMXBeanProxy(nameCreated, RuntimeMappingModuleMXBean.class);
273         return nameCreated;
274     }
275
276     private static ObjectName createDomData(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
277         final ObjectName nameCreated = transaction.createModule(DomInmemoryDataBrokerModuleFactory.NAME, DOM_INSTANCE_NAME);
278         final DomInmemoryDataBrokerModuleMXBean bean = transaction.newMXBeanProxy(nameCreated, DomInmemoryDataBrokerModuleMXBean.class);
279         bean.setSchemaService(createSchemaService(transaction));
280         return nameCreated;
281     }
282
283     private static ObjectName createSchemaService(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
284         final ObjectName nameCreated = transaction.createModule(SchemaServiceImplSingletonModuleFactory.NAME, SchemaServiceImplSingletonModuleFactory.SINGLETON_NAME);
285         transaction.newMXBeanProxy(nameCreated, SchemaServiceImplSingletonModuleMXBean.class);
286         return nameCreated;
287     }
288
289     private static ObjectName createDispatcher(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
290         return BmpDispatcherImplModuleTest.createInstance(transaction);
291     }
292 }