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