Bump netconf to use yangtools 1.2.0
[netconf.git] / netconf / netconf-it / src / test / java / org / opendaylight / netconf / it / AbstractNetconfConfigTest.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the terms of the Eclipse
5  * Public License v1.0 which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.it;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12
13 import com.google.common.base.Throwables;
14 import com.google.common.io.ByteStreams;
15 import com.google.common.util.concurrent.CheckedFuture;
16 import io.netty.channel.Channel;
17 import io.netty.channel.ChannelFuture;
18 import io.netty.channel.EventLoopGroup;
19 import io.netty.channel.local.LocalAddress;
20 import io.netty.channel.nio.NioEventLoopGroup;
21 import io.netty.util.HashedWheelTimer;
22 import io.netty.util.concurrent.GlobalEventExecutor;
23 import java.io.ByteArrayInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.InetSocketAddress;
27 import java.net.SocketAddress;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.concurrent.TimeUnit;
34 import org.junit.After;
35 import org.junit.Before;
36 import org.opendaylight.controller.config.facade.xml.ConfigSubsystemFacadeFactory;
37 import org.opendaylight.controller.config.facade.xml.osgi.EnumResolver;
38 import org.opendaylight.controller.config.facade.xml.osgi.YangStoreService;
39 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
40 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
41 import org.opendaylight.controller.config.spi.ModuleFactory;
42 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
43 import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
44 import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
45 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
46 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
47 import org.opendaylight.netconf.api.NetconfMessage;
48 import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
49 import org.opendaylight.netconf.client.NetconfClientDispatcherImpl;
50 import org.opendaylight.netconf.client.SimpleNetconfClientSessionListener;
51 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
52 import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
53 import org.opendaylight.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
54 import org.opendaylight.netconf.impl.NetconfServerDispatcherImpl;
55 import org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory;
56 import org.opendaylight.netconf.impl.SessionIdProvider;
57 import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
58 import org.opendaylight.netconf.impl.osgi.NetconfMonitoringServiceImpl;
59 import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
60 import org.opendaylight.netconf.monitoring.osgi.NetconfMonitoringActivator;
61 import org.opendaylight.netconf.monitoring.osgi.NetconfMonitoringOperationService;
62 import org.opendaylight.netconf.util.test.XmlFileLoader;
63 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
64 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
65 import org.opendaylight.yangtools.yang.binding.BindingMapping;
66 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
67 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
68 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
69 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
70 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
71 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
72 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
73 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
74 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
75
76 public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
77
78     public static final String LOOPBACK_ADDRESS = "127.0.0.1";
79     public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
80     private static final int RESOURCE_TIMEOUT_MINUTES = 2;
81
82     static ModuleFactory[] FACTORIES =
83             {new TestImplModuleFactory(), new DepTestImplModuleFactory(), new NetconfTestImplModuleFactory(),
84                     new IdentityTestModuleFactory(), new MultipleDependenciesModuleFactory()};
85
86     protected ConfigSubsystemFacadeFactory configSubsystemFacadeFactory;
87     private EventLoopGroup nettyThreadgroup;
88     private HashedWheelTimer hashedWheelTimer;
89
90     private NetconfClientDispatcherImpl clientDispatcher;
91     private Channel serverTcpChannel;
92
93     private NetconfMessage getConfig;
94     private NetconfMessage get;
95
96     /**
97      * @Before in subclasses is called after this method.
98      */
99     @Before
100     public void setUpAbstractNetconfConfigTest() throws Exception {
101         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
102
103         nettyThreadgroup = new NioEventLoopGroup();
104         hashedWheelTimer = new HashedWheelTimer();
105
106         loadMessages();
107
108         setUpTestInitial();
109
110         final AggregatedNetconfOperationServiceFactory factoriesListener =
111                 new AggregatedNetconfOperationServiceFactory();
112         final NetconfMonitoringService netconfMonitoringService = getNetconfMonitoringService(factoriesListener);
113         configSubsystemFacadeFactory =
114                 new ConfigSubsystemFacadeFactory(configRegistryClient, configRegistryClient, getYangStore());
115         factoriesListener.onAddNetconfOperationServiceFactory(
116                 new NetconfOperationServiceFactoryImpl(configSubsystemFacadeFactory));
117         factoriesListener.onAddNetconfOperationServiceFactory(
118                 new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
119                         new NetconfMonitoringOperationService(netconfMonitoringService)));
120
121         for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories(
122                 factoriesListener)) {
123             factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
124         }
125
126         serverTcpChannel = startNetconfTcpServer(factoriesListener, netconfMonitoringService);
127         clientDispatcher =
128                 new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
129     }
130
131     /**
132      * Called before setUp method is executed, so test classes can set up resources before
133      * setUpAbstractNetconfConfigTest method is called.
134      */
135     protected void setUpTestInitial() throws Exception {}
136
137     private void loadMessages() throws Exception {
138         this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
139         this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
140     }
141
142     public NetconfMessage getGetConfig() {
143         return getConfig;
144     }
145
146     public NetconfMessage getGet() {
147         return get;
148     }
149
150     private Channel startNetconfTcpServer(final AggregatedNetconfOperationServiceFactory listener,
151             final NetconfMonitoringService monitoring) throws Exception {
152         final NetconfServerDispatcherImpl dispatch = createDispatcher(listener, monitoring);
153
154         final ChannelFuture s;
155         if (getTcpServerAddress() instanceof LocalAddress) {
156             s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
157         } else {
158             s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
159         }
160         s.await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
161         return s.channel();
162     }
163
164     protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories(
165             final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
166         return Collections.emptySet();
167     }
168
169     protected NetconfMonitoringService getNetconfMonitoringService(
170             final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
171         return new NetconfMonitoringServiceImpl(factoriesListener);
172     }
173
174     protected abstract SocketAddress getTcpServerAddress();
175
176     public NetconfClientDispatcherImpl getClientDispatcher() {
177         return clientDispatcher;
178     }
179
180     private HardcodedYangStoreService getYangStore() throws IOException {
181         final Collection<InputStream> yangDependencies = getBasicYangs();
182         return new HardcodedYangStoreService(yangDependencies, getBindingRuntimeContext());
183     }
184
185     static Collection<InputStream> getBasicYangs() throws IOException {
186
187         final List<String> paths = Arrays.asList("/META-INF/yang/config@2013-04-05.yang",
188                 "/META-INF/yang/rpc-context@2013-06-17.yang",
189                 "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang",
190                 "/META-INF/yang/test-types.yang", "/META-INF/yang/test-groups.yang",
191                 "/META-INF/yang/ietf-inet-types@2013-07-15.yang");
192
193         final Collection<InputStream> yangDependencies = new ArrayList<>();
194         final List<String> failedToFind = new ArrayList<>();
195         for (final String path : paths) {
196             final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
197             if (resourceAsStream == null) {
198                 failedToFind.add(path);
199             } else {
200                 yangDependencies.add(resourceAsStream);
201             }
202         }
203         assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
204         return yangDependencies;
205     }
206
207     protected NetconfServerDispatcherImpl createDispatcher(
208             final AggregatedNetconfOperationServiceFactory factoriesListener,
209             final NetconfMonitoringService sessionMonitoringService) {
210         final SessionIdProvider idProvider = new SessionIdProvider();
211
212         final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory =
213                 new NetconfServerSessionNegotiatorFactory(hashedWheelTimer, factoriesListener, idProvider,
214                         SERVER_CONNECTION_TIMEOUT_MILLIS, sessionMonitoringService);
215
216         final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer =
217                 new NetconfServerDispatcherImpl.ServerChannelInitializer(serverNegotiatorFactory);
218         return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
219     }
220
221     protected HashedWheelTimer getHashedWheelTimer() {
222         return hashedWheelTimer;
223     }
224
225     protected EventLoopGroup getNettyThreadgroup() {
226         return nettyThreadgroup;
227     }
228
229     /**
230      * @After in subclasses is be called before this.
231      */
232     @After
233     public void cleanUpNetconf() throws Exception {
234         serverTcpChannel.close().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
235         hashedWheelTimer.stop();
236         nettyThreadgroup.shutdownGracefully().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
237     }
238
239     public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
240         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
241         b.withAddress(tcpAddress);
242         b.withSessionListener(new SimpleNetconfClientSessionListener());
243         b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
244         b.withConnectionTimeoutMillis(timeout);
245         return b.build();
246     }
247
248     public static final class HardcodedYangStoreService extends YangStoreService {
249         public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams,
250                 final BindingRuntimeContext bindingRuntimeContext) throws IOException {
251             super(new SchemaContextProvider() {
252                 @Override
253                 public SchemaContext getSchemaContext() {
254                     return getSchema(inputStreams);
255                 }
256             }, new SchemaSourceProvider<YangTextSchemaSource>() {
257                 @Override
258                 public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> getSource(
259                         SourceIdentifier sourceIdentifier) {
260
261                     return null;
262                 }
263             });
264
265             refresh(bindingRuntimeContext);
266         }
267
268         private static SchemaContext getSchema(final Collection<? extends InputStream> inputStreams) {
269             final ArrayList<InputStream> byteArrayInputStreams = new ArrayList<>();
270             for (final InputStream inputStream : inputStreams) {
271                 assertNotNull(inputStream);
272                 final byte[] content;
273                 try {
274                     content = ByteStreams.toByteArray(inputStream);
275                 } catch (IOException e) {
276                     throw new IllegalStateException("Cannot read " + inputStream, e);
277                 }
278                 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
279                 byteArrayInputStreams.add(byteArrayInputStream);
280             }
281
282             for (final InputStream inputStream : byteArrayInputStreams) {
283                 try {
284                     inputStream.reset();
285                 } catch (final IOException e) {
286                     throw new RuntimeException(e);
287                 }
288             }
289
290             try {
291                 return YangInferencePipeline.RFC6020_REACTOR.newBuild().buildEffective(byteArrayInputStreams);
292             } catch (SourceException | ReactorException e) {
293                 throw Throwables.propagate(e);
294             }
295         }
296
297         @Override
298         public EnumResolver getEnumResolver() {
299             return new EnumResolver() {
300                 @Override
301                 public String fromYang(final String enumType, final String enumYangValue) {
302                     return BindingMapping.getClassName(enumYangValue);
303                 }
304
305                 @Override
306                 public String toYang(final String enumType, final String enumJavaValue) {
307                     return enumJavaValue.toLowerCase();
308                 }
309             };
310         }
311     }
312 }