BUG-731: RoutedRegistration.close() should not throw
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / test / java / org / opendaylight / controller / sal / binding / test / util / BindingTestContext.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.sal.binding.test.util;
9
10 import static com.google.common.base.Preconditions.checkState;
11
12 import java.io.InputStream;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.concurrent.Future;
17
18 import javassist.ClassPool;
19
20 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
23 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
24 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
25 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
26 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
27 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
28 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
29 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
30 import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
31 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
32 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
33 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
34 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
35 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
36 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
37 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
38 import org.opendaylight.controller.sal.core.api.BrokerService;
39 import org.opendaylight.controller.sal.core.api.RpcImplementation;
40 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
41 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
42 import org.opendaylight.controller.sal.core.api.data.DataStore;
43 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
44 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
45 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
46 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
47 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
48 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
49 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
50 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
51 import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
52 import org.opendaylight.yangtools.concepts.ListenerRegistration;
53 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
54 import org.opendaylight.yangtools.yang.common.QName;
55 import org.opendaylight.yangtools.yang.common.RpcResult;
56 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
57 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
58 import org.opendaylight.yangtools.yang.model.api.Module;
59 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
60 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
61 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
62 import org.reflections.Reflections;
63 import org.reflections.scanners.ResourcesScanner;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 import com.google.common.base.Predicate;
68 import com.google.common.collect.ClassToInstanceMap;
69 import com.google.common.collect.ImmutableClassToInstanceMap;
70 import com.google.common.collect.ImmutableMap;
71 import com.google.common.util.concurrent.ListeningExecutorService;
72
73 public class BindingTestContext implements AutoCloseable, SchemaContextProvider {
74
75     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
76             .builder().toInstance();
77
78     private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
79
80     private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
81
82     private DomForwardedBindingBrokerImpl baBrokerImpl;
83     private DataBrokerImpl baDataImpl;
84     private NotificationBrokerImpl baNotifyImpl;
85     private BindingIndependentConnector baConnectImpl;
86
87     private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
88     private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
89     private BrokerImpl biBrokerImpl;
90     private HashMapDataStore rawDataStore;
91     private SchemaAwareDataStoreAdapter schemaAwareDataStore;
92     private DataStoreStatsWrapper dataStoreStats;
93     private DataStore dataStore;
94
95     private final boolean dataStoreStatisticsEnabled = false;
96
97     private final ListeningExecutorService executor;
98     private final ClassPool classPool;
99
100     private final boolean startWithSchema;
101
102     private MountPointManagerImpl biMountImpl;
103
104     private SchemaContext schemaContext;
105
106     private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
107
108     private BackwardsCompatibleDataBroker biCompatibleBroker;
109
110     private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
111
112     private DataProviderService baData;
113
114     private DOMDataBroker newDOMDataBroker;
115
116     @Override
117     public SchemaContext getSchemaContext() {
118         return schemaContext;
119     }
120
121     public DOMDataBroker getDomAsyncDataBroker() {
122         return newDOMDataBroker;
123     }
124
125     protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
126         this.executor = executor;
127         this.classPool = classPool;
128         this.startWithSchema = startWithSchema;
129     }
130
131     public void startDomDataStore() {
132         checkState(dataStore == null, "DataStore already started.");
133         checkState(biDataImpl != null, "Dom Data Broker not present");
134         rawDataStore = new HashMapDataStore();
135         schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
136         schemaAwareDataStore.changeDelegate(rawDataStore);
137         if (dataStoreStatisticsEnabled) {
138             dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
139             dataStore = dataStoreStats;
140         } else {
141             dataStore = schemaAwareDataStore;
142         }
143
144         biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
145         biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
146         biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
147     }
148
149     public void startDomDataBroker() {
150         checkState(executor != null, "Executor needs to be set");
151         biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
152         biDataImpl.setExecutor(executor);
153         biDataLegacyBroker = biDataImpl;
154     }
155
156     public void startNewDomDataBroker() {
157         checkState(executor != null, "Executor needs to be set");
158         InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", executor);
159         InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", executor);
160         newDatastores = ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
161                 .put(LogicalDatastoreType.OPERATIONAL, operStore)
162                 .put(LogicalDatastoreType.CONFIGURATION, configStore)
163                 .build();
164
165         newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
166
167         biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
168
169         schemaListeners.add(configStore);
170         schemaListeners.add(operStore);
171         schemaListeners.add(biCompatibleBroker);
172         biDataLegacyBroker = biCompatibleBroker;
173     }
174
175     public void startBindingDataBroker() {
176         checkState(executor != null, "Executor needs to be set");
177         baDataImpl = new DataBrokerImpl();
178         baDataImpl.setExecutor(executor);
179         baData = baDataImpl;
180     }
181
182     public void startBindingBroker() {
183         checkState(executor != null, "Executor needs to be set");
184         checkState(baData != null, "Binding Data Broker must be started");
185         checkState(baNotifyImpl != null, "Notification Service must be started");
186         baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
187
188         baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
189         baBrokerImpl.getMountManager().setNotificationExecutor(executor);
190         baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
191         baBrokerImpl.setDataBroker(baData);
192         baBrokerImpl.setNotificationBroker(baNotifyImpl);
193         baBrokerImpl.start();
194     }
195
196     public void startForwarding() {
197         checkState(baData != null, "Binding Data Broker needs to be started");
198         checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
199         checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
200
201         baConnectImpl = BindingDomConnectorDeployer.createConnector(getBindingToDomMappingService());
202         baConnectImpl.setDomRpcRegistry(getDomRpcRegistry());
203         baBrokerImpl.setConnector(baConnectImpl);
204         baBrokerImpl.setDomProviderContext(createMockContext());
205         baBrokerImpl.startForwarding();
206     }
207
208     private ProviderSession createMockContext() {
209
210         final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
211                 .<BrokerService> builder()
212                 //
213                 .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
214                 .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
215                 .put(MountProvisionService.class, biMountImpl) //
216                 .build();
217
218         return new ProviderSession() {
219
220             @Override
221             public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
222                 throw new UnsupportedOperationException();
223             }
224
225             @Override
226             public <T extends BrokerService> T getService(final Class<T> service) {
227                 return domBrokerServices.getInstance(service);
228             }
229
230             @Override
231             public boolean isClosed() {
232                 return false;
233             }
234
235             @Override
236             public Set<QName> getSupportedRpcs() {
237                 return null;
238             }
239
240             @Override
241             public void close() {
242             }
243
244             @Override
245             public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
246                     final RpcRegistrationListener listener) {
247                 return null;
248             }
249
250             @Override
251             public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
252                     throws IllegalArgumentException {
253                 return null;
254             }
255
256             @Override
257             public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
258                 return null;
259             }
260
261             @Override
262             public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
263                 return null;
264             }
265         };
266     }
267
268     public void startBindingToDomMappingService() {
269         checkState(classPool != null, "ClassPool needs to be present");
270         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
271         mappingServiceImpl.setPool(classPool);
272         mappingServiceImpl.init();
273     }
274
275     public void updateYangSchema(final String[] files) {
276         schemaContext = getContext(files);
277
278         if (schemaAwareDataStore != null) {
279             schemaAwareDataStore.onGlobalContextUpdated(schemaContext);
280         }
281         if (mappingServiceImpl != null) {
282             mappingServiceImpl.onGlobalContextUpdated(schemaContext);
283         }
284         for(SchemaContextListener listener : schemaListeners) {
285             listener.onGlobalContextUpdated(schemaContext);
286         }
287     }
288
289     public static String[] getAllYangFilesOnClasspath() {
290         Predicate<String> predicate = new Predicate<String>() {
291             @Override
292             public boolean apply(final String input) {
293                 return input.endsWith(".yang");
294             }
295         };
296         Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
297         Set<String> result = reflection.getResources(predicate);
298         return result.toArray(new String[result.size()]);
299     }
300
301     private static SchemaContext getContext(final String[] yangFiles) {
302         ClassLoader loader = BindingTestContext.class.getClassLoader();
303         List<InputStream> streams = new ArrayList<>();
304         for (String string : yangFiles) {
305             InputStream stream = loader.getResourceAsStream(string);
306             streams.add(stream);
307         }
308         YangParserImpl parser = new YangParserImpl();
309         Set<Module> modules = parser.parseYangModelsFromStreams(streams);
310         return parser.resolveSchemaContext(modules);
311     }
312
313     public void startLegacy() {
314         startBindingDataBroker();
315         startBindingNotificationBroker();
316         startBindingBroker();
317         startDomDataBroker();
318         startDomDataStore();
319         startDomBroker();
320         startDomMountPoint();
321         startBindingToDomMappingService();
322         startForwarding();
323         if (startWithSchema) {
324             loadYangSchemaFromClasspath();
325         }
326     }
327
328     public void start() {
329         startNewDomDataBroker();
330         startDomBroker();
331         startDomMountPoint();
332         startBindingToDomMappingService();
333         startNewBindingDataBroker();
334
335         startBindingNotificationBroker();
336         startBindingBroker();
337
338         startForwarding();
339         if (startWithSchema) {
340             loadYangSchemaFromClasspath();
341         }
342     }
343
344     public void startNewBindingDataBroker() {
345         ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
346         schemaListeners.add(forwarded);
347         baData = forwarded;
348     }
349
350     private void startDomMountPoint() {
351         biMountImpl = new MountPointManagerImpl();
352         biMountImpl.setDataBroker(getDomDataBroker());
353     }
354
355     private void startDomBroker() {
356         checkState(executor != null);
357         biBrokerImpl = new BrokerImpl();
358         biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
359
360     }
361
362     public void startBindingNotificationBroker() {
363         checkState(executor != null);
364         baNotifyImpl = new NotificationBrokerImpl(executor);
365
366     }
367
368     public void loadYangSchemaFromClasspath() {
369         String[] files = getAllYangFilesOnClasspath();
370         updateYangSchema(files);
371     }
372
373     public DataProviderService getBindingDataBroker() {
374         return baData;
375     }
376
377     public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
378         return biDataLegacyBroker;
379     }
380
381     public DataStore getDomDataStore() {
382         return dataStore;
383     }
384
385     public BindingIndependentMappingService getBindingToDomMappingService() {
386         return mappingServiceImpl;
387     }
388
389     public void logDataStoreStatistics() {
390         if (dataStoreStats == null) {
391             return;
392         }
393
394         LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
395                 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
396                 dataStoreStats.getConfigurationReadAverageTime());
397
398         LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
399                 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
400                 dataStoreStats.getOperationalReadAverageTime());
401
402         LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
403                 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
404                 dataStoreStats.getRequestCommitAverageTime());
405     }
406
407     public RpcProviderRegistry getBindingRpcRegistry() {
408         return baBrokerImpl.getRoot();
409     }
410
411     public RpcProvisionRegistry getDomRpcRegistry() {
412         if (biBrokerImpl == null) {
413             return null;
414         }
415         return biBrokerImpl.getRouter();
416     }
417
418     public RpcImplementation getDomRpcInvoker() {
419         return biBrokerImpl.getRouter();
420     }
421
422     @Override
423     public void close() throws Exception {
424
425     }
426
427     public MountProviderService getBindingMountProviderService() {
428         return baBrokerImpl.getMountManager();
429     }
430
431     public MountProvisionService getDomMountProviderService() {
432         return biMountImpl;
433     }
434 }