Bug 6859 - Binding generator v1 refactoring
[bgpcep.git] / programming / impl / src / test / java / org / opendaylight / controller / config / yang / programming / impl / AbstractInstructionSchedulerTest.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.programming.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
18 import com.google.common.base.Throwables;
19 import com.google.common.collect.Lists;
20 import io.netty.channel.EventLoopGroup;
21 import io.netty.channel.nio.NioEventLoopGroup;
22 import io.netty.util.Timer;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Dictionary;
29 import java.util.List;
30 import java.util.Set;
31 import javax.management.InstanceAlreadyExistsException;
32 import javax.management.InstanceNotFoundException;
33 import javax.management.ObjectName;
34 import org.junit.After;
35 import org.junit.Assert;
36 import org.junit.Before;
37 import org.mockito.Matchers;
38 import org.mockito.Mock;
39 import org.mockito.Mockito;
40 import org.mockito.MockitoAnnotations;
41 import org.mockito.invocation.InvocationOnMock;
42 import org.mockito.stubbing.Answer;
43 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
44 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
45 import org.opendaylight.controller.config.spi.ModuleFactory;
46 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
47 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleFactory;
48 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleMXBean;
49 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingBrokerImplModuleFactory;
50 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingBrokerImplModuleMXBean;
51 import org.opendaylight.controller.config.yang.md.sal.binding.impl.ForwardedCompatibleDataBrokerImplModuleFactory;
52 import org.opendaylight.controller.config.yang.md.sal.binding.impl.ForwardedCompatibleDataBrokerImplModuleMXBean;
53 import org.opendaylight.controller.config.yang.md.sal.binding.impl.NotificationBrokerImplModuleFactory;
54 import org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModuleFactory;
55 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleFactory;
56 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleMXBean;
57 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleFactory;
58 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleMXBean;
59 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleFactory;
60 import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
61 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
62 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory;
63 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
64 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
65 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
66 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
67 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation;
68 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration;
69 import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
70 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
71 import org.opendaylight.controller.sal.core.api.model.SchemaService;
72 import org.opendaylight.controller.sal.core.api.model.YangTextSourceProvider;
73 import org.opendaylight.mdsal.binding.generator.api.ClassLoadingStrategy;
74 import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
75 import org.opendaylight.yangtools.concepts.ListenerRegistration;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
78 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
79 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
80 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
81 import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver;
82 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
83 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
84 import org.osgi.framework.Bundle;
85 import org.osgi.framework.BundleListener;
86 import org.osgi.framework.Filter;
87 import org.osgi.framework.ServiceListener;
88 import org.osgi.framework.ServiceReference;
89
90 public abstract class AbstractInstructionSchedulerTest extends AbstractConfigTest {
91
92     private static final String FACTORY_NAME = InstructionSchedulerImplModuleFactory.NAME;
93     private static final String INSTANCE_NAME = "instruction-scheduler-impl";
94
95     private static final String BINDING_BROKER_INSTANCE_NAME = "binding-broker-impl";
96     private static final String NOTIFICATION_BROKER_INSTANCE_NAME = "notification-broker-impl";
97     private static final String COMPATIBLE_DATA_BROKER_INSTANCE_NAME = "binding-data-compatible-broker-instance";
98     private static final String DOM_BROKER_INSTANCE_NAME = "dom-broker-impl";
99     private static final String TIMER_INSTANCE_NAME = "timer-impl";
100     private static final String BINDING_ASYNC_BROKER_INSTANCE_NAME = "binding-async-broker-instance";
101     private static final String DOM_ASYNC_DATA_BROKER_INSTANCE = "dom-inmemory-data-broker";
102
103     @Mock
104     private RpcResult<TransactionStatus> mockedResult;
105
106     @SuppressWarnings("unchecked")
107     @Before
108     public void setUp() throws Exception {
109         MockitoAnnotations.initMocks(this);
110
111         final List<ModuleFactory> moduleFactories = getModuleFactories();
112         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.mockedContext, moduleFactories.toArray(new ModuleFactory[moduleFactories.size()])));
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(this.mockedContext).createFilter(anyString());
123
124         Mockito.doReturn(new ServiceReference[] {}).when(this.mockedContext).getServiceReferences(Matchers.anyString(), Matchers.anyString());
125
126         final ServiceReference<?> classLoadingStrategySR = mock(ServiceReference.class, "ClassLoadingStrategy");
127         final ServiceReference<?> emptyServiceReference = mock(ServiceReference.class, "Empty");
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("Class loading stategy reference").when(classLoadingStrategySR).toString();
140         Mockito.doReturn("Empty reference").when(emptyServiceReference).toString();
141
142         Mockito.doReturn(emptyServiceReference).when(this.mockedContext).getServiceReference(any(Class.class));
143         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(GeneratedClassLoadingStrategy.class);
144         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(ClassLoadingStrategy.class);
145
146         Mockito.doReturn(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()).when(this.mockedContext).getService(classLoadingStrategySR);
147         Mockito.doReturn(null).when(this.mockedContext).getService(emptyServiceReference);
148
149         final SchemaContext context = parseYangStreams(getFilesAsStreams(getYangModelsPaths()));
150         final SchemaService mockedSchemaService = mock(SchemaService.class);
151         doReturn(context).when(mockedSchemaService).getGlobalContext();
152         doAnswer(new Answer<ListenerRegistration<SchemaContextListener>>() {
153             @Override
154             public ListenerRegistration<SchemaContextListener> answer(final InvocationOnMock invocation) {
155                 invocation.getArgumentAt(0, SchemaContextListener.class).onGlobalContextUpdated(context);
156                 final ListenerRegistration<SchemaContextListener> reg = mock(ListenerRegistration.class);
157                 doNothing().when(reg).close();
158                 return reg;
159             }
160         }).when(mockedSchemaService).registerSchemaContextListener(any(SchemaContextListener.class));
161
162         setupMockService(SchemaService.class, mockedSchemaService);
163         setupMockService(YangTextSourceProvider.class, mock(YangTextSourceProvider.class));
164
165         final BindingToNormalizedNodeCodec bindingCodec = BindingToNormalizedNodeCodecFactory.newInstance(
166                 GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
167         BindingToNormalizedNodeCodecFactory.registerInstance(bindingCodec, mockedSchemaService);
168         setupMockService(BindingToNormalizedNodeCodec.class, bindingCodec);
169
170         setupMockService(Timer.class, mock(Timer.class));
171         setupMockService(EventLoopGroup.class, new NioEventLoopGroup());
172         setupMockService(DOMNotificationService.class, mock(DOMNotificationService.class));
173         setupMockService(DOMNotificationPublishService.class, mock(DOMNotificationPublishService.class));
174         setupMockService(DOMRpcService.class, mock(DOMRpcService.class));
175         setupMockService(DOMMountPointService.class, mock(DOMMountPointService.class));
176
177         final DOMRpcProviderService mockRpcProvider = mock(DOMRpcProviderService.class);
178         doReturn(mock(DOMRpcImplementationRegistration.class)).when(mockRpcProvider).registerRpcImplementation(
179                 any(DOMRpcImplementation.class), any(Set.class));
180         setupMockService(DOMRpcProviderService.class, mockRpcProvider);
181     }
182
183     protected void setupMockService(final Class<?> serviceInterface, final Object instance) throws Exception {
184         final ServiceReference<?> mockServiceRef = mock(ServiceReference.class);
185         doReturn(new ServiceReference[]{mockServiceRef}).when(this.mockedContext).
186                 getServiceReferences(anyString(), contains(serviceInterface.getName()));
187         doReturn(new ServiceReference[]{mockServiceRef}).when(this.mockedContext).
188                 getServiceReferences(serviceInterface.getName(), null);
189         doReturn(instance).when(this.mockedContext).getService(mockServiceRef);
190     }
191
192     @After
193     public void tearDownGlobalBundleScanningSchemaServiceImpl() throws Exception{
194     }
195
196     public ObjectName createInstructionSchedulerModuleInstance(final ConfigTransactionJMXClient transaction, final ObjectName dataBrokerON,
197             final ObjectName rpcRegistyON, final ObjectName notificationBrokerON) throws Exception {
198         final ObjectName objectName = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
199         final InstructionSchedulerImplModuleMXBean mxBean = transaction.newMXBeanProxy(objectName,
200                 InstructionSchedulerImplModuleMXBean.class);
201         mxBean.setDataProvider(dataBrokerON);
202         mxBean.setRpcRegistry(rpcRegistyON);
203         mxBean.setNotificationService(notificationBrokerON);
204         mxBean.setTimer(createTimerInstance(transaction));
205         return objectName;
206     }
207
208     private ObjectName createTimerInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
209         final ObjectName nameCreated = transaction.createModule(HashedWheelTimerModuleFactory.NAME, TIMER_INSTANCE_NAME);
210         return nameCreated;
211
212     }
213
214     public ObjectName createBindingBrokerImpl(final ConfigTransactionJMXClient transaction, final ObjectName dataBrokerON,
215             final ObjectName notificationBrokerON) throws Exception {
216         final ObjectName objectName = transaction.createModule(BindingBrokerImplModuleFactory.NAME, BINDING_BROKER_INSTANCE_NAME);
217         final BindingBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(objectName, BindingBrokerImplModuleMXBean.class);
218         mxBean.setDataBroker(dataBrokerON);
219         mxBean.setNotificationService(notificationBrokerON);
220         mxBean.setBindingMappingService(lookupMappingServiceInstance(transaction));
221         mxBean.setDomAsyncBroker(lookupDomBrokerInstance(transaction));
222         return objectName;
223     }
224
225     public ObjectName createNotificationBrokerInstance(final ConfigTransactionJMXClient transaction) throws Exception {
226         final ObjectName objectName = transaction.createModule(NotificationBrokerImplModuleFactory.NAME, NOTIFICATION_BROKER_INSTANCE_NAME);
227         return objectName;
228     }
229
230     public ObjectName createCompatibleDataBrokerInstance(final ConfigTransactionJMXClient transaction)
231             throws InstanceAlreadyExistsException, InstanceNotFoundException {
232         final ObjectName nameCreated = transaction.createModule(ForwardedCompatibleDataBrokerImplModuleFactory.NAME, COMPATIBLE_DATA_BROKER_INSTANCE_NAME);
233         final ForwardedCompatibleDataBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, ForwardedCompatibleDataBrokerImplModuleMXBean.class);
234         mxBean.setDataBroker(lookupDataBrokerInstance(transaction));
235         return nameCreated;
236     }
237
238     private static ObjectName lookupDataBrokerInstance(final ConfigTransactionJMXClient transaction) {
239         try {
240             return transaction.lookupConfigBean(BindingAsyncDataBrokerImplModuleFactory.NAME, BINDING_ASYNC_BROKER_INSTANCE_NAME);
241         } catch (final InstanceNotFoundException e) {
242             try {
243                 return transaction.createModule(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
244             } catch (final InstanceAlreadyExistsException e1) {
245                 throw new IllegalStateException(e1);
246             }
247         }
248     }
249
250     public ObjectName createAsyncDataBrokerInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException, InstanceNotFoundException {
251         final ObjectName nameCreated = transaction.createModule(BindingAsyncDataBrokerImplModuleFactory.NAME, BINDING_ASYNC_BROKER_INSTANCE_NAME);
252         final BindingAsyncDataBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, BindingAsyncDataBrokerImplModuleMXBean.class);
253         mxBean.setBindingMappingService(lookupMappingServiceInstance(transaction));
254         mxBean.setDomAsyncBroker(lookupDomAsyncDataBroker(transaction));
255         mxBean.setSchemaService(lookupSchemaServiceInstance(transaction));
256         return nameCreated;
257     }
258
259     private static ObjectName lookupMappingServiceInstance(final ConfigTransactionJMXClient transaction) {
260         try {
261             return transaction.lookupConfigBean(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
262         } catch (final InstanceNotFoundException e) {
263             try {
264                 return transaction.createModule(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
265             } catch (final InstanceAlreadyExistsException e1) {
266                 throw new IllegalStateException(e1);
267             }
268         }
269     }
270
271     private static ObjectName lookupSchemaServiceInstance(final ConfigTransactionJMXClient transaction) {
272         try {
273             return transaction.lookupConfigBean(SchemaServiceImplSingletonModuleFactory.NAME, SchemaServiceImplSingletonModuleFactory.SINGLETON_NAME);
274         } catch (final InstanceNotFoundException e) {
275             try {
276                 return transaction.createModule(SchemaServiceImplSingletonModuleFactory.NAME, SchemaServiceImplSingletonModuleFactory.SINGLETON_NAME);
277             } catch (final InstanceAlreadyExistsException e1) {
278                 throw new IllegalStateException(e1);
279             }
280         }
281     }
282
283     public static ObjectName lookupDomBrokerInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
284         try {
285             return transaction.lookupConfigBean(DomBrokerImplModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
286         } catch (final InstanceNotFoundException e) {
287             try {
288                 final ObjectName nameCreated = transaction.createModule(DomBrokerImplModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
289                 final DomBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, DomBrokerImplModuleMXBean.class);
290                 mxBean.setAsyncDataBroker(lookupDomAsyncDataBroker(transaction));
291                 return nameCreated;
292             } catch (final InstanceAlreadyExistsException e1) {
293                 throw new IllegalStateException(e1);
294             }
295         }
296     }
297
298     private static ObjectName lookupDomAsyncDataBroker(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
299         try {
300             return transaction.lookupConfigBean(DomInmemoryDataBrokerModuleFactory.NAME, DOM_ASYNC_DATA_BROKER_INSTANCE);
301         } catch (final InstanceNotFoundException e) {
302             try {
303                 final ObjectName nameCreated = transaction.createModule(DomInmemoryDataBrokerModuleFactory.NAME, DOM_ASYNC_DATA_BROKER_INSTANCE);
304                 final DomInmemoryDataBrokerModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, DomInmemoryDataBrokerModuleMXBean.class);
305                 mxBean.setSchemaService(lookupSchemaServiceInstance(transaction));
306                 return nameCreated;
307             } catch (final InstanceAlreadyExistsException e1) {
308                 throw new IllegalStateException(e1);
309             }
310         }
311     }
312
313     @Override
314     protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(final Class<?> serviceType) {
315         if (serviceType.equals(SchemaContextListener.class)) {
316             return new BundleContextServiceRegistrationHandler() {
317                 @Override
318                 public void handleServiceRegistration(final Class<?> clazz, final Object serviceInstance, final Dictionary<String, ?> props) {
319                     final SchemaContextListener listener = (SchemaContextListener) serviceInstance;
320                     final SchemaContext context = parseYangStreams(getFilesAsStreams(getYangModelsPaths()));
321                     listener.onGlobalContextUpdated(context);
322                     listener.onGlobalContextUpdated(context);
323                 }
324             };
325         }
326         return super.getBundleContextServiceRegistrationHandler(serviceType);
327     }
328
329     public List<String> getYangModelsPaths() {
330         return Lists.newArrayList("/META-INF/yang/ietf-inet-types@2013-07-15.yang", "/META-INF/yang/programming.yang");
331     }
332
333     public List<ModuleFactory> getModuleFactories() {
334         return Lists.newArrayList(new InstructionSchedulerImplModuleFactory(), new HashedWheelTimerModuleFactory(),
335                 new NotificationBrokerImplModuleFactory(), new DomBrokerImplModuleFactory(),
336                 new RuntimeMappingModuleFactory(), new BindingBrokerImplModuleFactory(), new BindingAsyncDataBrokerImplModuleFactory(),
337                 new DomInmemoryDataBrokerModuleFactory(), new SchemaServiceImplSingletonModuleFactory(),
338                 new ForwardedCompatibleDataBrokerImplModuleFactory());
339     }
340
341     // TODO move back to AbstractConfigTest
342     private static List<InputStream> getFilesAsStreams(final List<String> paths) {
343         final List<InputStream> resources = new ArrayList<>();
344         final List<String> failedToFind = new ArrayList<>();
345         for (final String path : paths) {
346             final InputStream is = AbstractInstructionSchedulerTest.class.getResourceAsStream(path);
347             if (is == null) {
348                 failedToFind.add(path);
349             } else {
350                 resources.add(is);
351             }
352         }
353         Assert.assertEquals("Some files were not found", Collections.emptyList(), failedToFind);
354
355         return resources;
356     }
357
358     private static YangTextSchemaContextResolver newSchemaContextResolver(final List<String> paths) {
359         final YangTextSchemaContextResolver resolver = YangTextSchemaContextResolver.create("test");
360         final List<String> failedToFind = new ArrayList<>();
361         for (final String path : paths) {
362             final URL url = AbstractInstructionSchedulerTest.class.getResource(path);
363             if (url == null) {
364                 failedToFind.add(path);
365             } else {
366                 try {
367                     resolver.registerSource(url);
368                 } catch (SchemaSourceException | IOException | YangSyntaxErrorException e) {
369                     Throwables.propagate(e);
370                 }
371             }
372         }
373         Assert.assertEquals("Some files were not found", Collections.<String> emptyList(), failedToFind);
374         return resolver;
375     }
376
377     private static SchemaContext parseYangStreams(final List<InputStream> streams) {
378         try {
379             return YangParserTestUtils.parseYangStreams(streams);
380         } catch (final ReactorException e) {
381             throw new RuntimeException("Unable to build schema context from " + streams, e);
382         }
383     }
384
385 }