Refactor integration tests for netconf in netconf-it
[controller.git] / opendaylight / netconf / netconf-it / src / test / java / org / opendaylight / controller / 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
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.netconf.it;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Matchers.anySetOf;
14 import static org.mockito.Matchers.anyString;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
18
19 import io.netty.channel.Channel;
20 import io.netty.channel.ChannelFuture;
21 import io.netty.channel.EventLoopGroup;
22 import io.netty.channel.local.LocalAddress;
23 import io.netty.channel.nio.NioEventLoopGroup;
24 import io.netty.util.HashedWheelTimer;
25 import io.netty.util.concurrent.GlobalEventExecutor;
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.net.InetSocketAddress;
30 import java.net.SocketAddress;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashSet;
36 import java.util.List;
37 import org.apache.commons.io.IOUtils;
38 import org.junit.After;
39 import org.junit.Before;
40 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
41 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
42 import org.opendaylight.controller.config.spi.ModuleFactory;
43 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
44 import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
45 import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
46 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
47 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
48 import org.opendaylight.controller.netconf.api.NetconfMessage;
49 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
50 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
51 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
52 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
53 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
54 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
55 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
56 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl;
57 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
58 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
59 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
60 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
61 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
62 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
63 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
64 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
65 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
66 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
67 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
68 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
69 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
70 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
71 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
72 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
73 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
74 import org.w3c.dom.Element;
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
81     static ModuleFactory[] FACTORIES = { new TestImplModuleFactory(),
82             new DepTestImplModuleFactory(), new NetconfTestImplModuleFactory(),
83             new IdentityTestModuleFactory(), new MultipleDependenciesModuleFactory() };
84
85     private EventLoopGroup nettyThreadgroup;
86     private HashedWheelTimer hashedWheelTimer;
87
88     private NetconfClientDispatcherImpl clientDispatcher;
89     private Channel serverTcpChannel;
90
91     private NetconfMessage getConfig;
92     private NetconfMessage get;
93
94     /**
95      * @Before in subclasses is called after this method.
96      */
97     @Before
98     public void setUpAbstractNetconfConfigTest() throws Exception {
99         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
100
101         nettyThreadgroup = new NioEventLoopGroup();
102         hashedWheelTimer = new HashedWheelTimer();
103
104         loadMessages();
105
106         setUpTestInitial();
107
108         final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
109         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
110
111         for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories()) {
112             factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
113         }
114
115         serverTcpChannel = startNetconfTcpServer(factoriesListener);
116         clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
117     }
118
119     /**
120      * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
121      */
122     protected void setUpTestInitial() throws Exception {}
123
124     private void loadMessages() throws Exception {
125         this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
126         this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
127     }
128
129     public NetconfMessage getGetConfig() {
130         return getConfig;
131     }
132
133     public NetconfMessage getGet() {
134         return get;
135     }
136
137     private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception {
138         final NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer());
139
140         final ChannelFuture s;
141         if(getTcpServerAddress() instanceof LocalAddress) {
142             s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
143         } else {
144             s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
145         }
146         s.await();
147         return s.channel();
148     }
149
150     protected DefaultCommitNotificationProducer getNotificationProducer() {
151         final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
152         doNothing().when(notificationProducer).close();
153         doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
154         return notificationProducer;
155     }
156
157     protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
158         return Collections.emptySet();
159     }
160
161     protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
162         final NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class);
163         final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
164         doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
165         doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString());
166         return new NetconfMonitoringServiceImpl(netconfOperationProvider);
167     }
168
169     protected abstract SocketAddress getTcpServerAddress();
170
171     public NetconfClientDispatcherImpl getClientDispatcher() {
172         return clientDispatcher;
173     }
174
175     private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
176         final Collection<InputStream> yangDependencies = getBasicYangs();
177         return new HardcodedYangStoreService(yangDependencies);
178     }
179
180     static Collection<InputStream> getBasicYangs() throws IOException {
181
182         final List<String> paths = Arrays.asList(
183                 "/META-INF/yang/config.yang",
184                 "/META-INF/yang/rpc-context.yang",
185                 "/META-INF/yang/config-test.yang",
186                 "/META-INF/yang/config-test-impl.yang",
187                 "/META-INF/yang/test-types.yang",
188                 "/META-INF/yang/ietf-inet-types.yang");
189
190         final Collection<InputStream> yangDependencies = new ArrayList<>();
191         final List<String> failedToFind = new ArrayList<>();
192         for (final String path : paths) {
193             final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
194             if (resourceAsStream == null) {
195                 failedToFind.add(path);
196             } else {
197                 yangDependencies.add(resourceAsStream);
198             }
199         }
200         assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
201         return yangDependencies;
202     }
203
204     protected NetconfServerDispatcher createDispatcher(
205             final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService,
206             final DefaultCommitNotificationProducer commitNotifier) {
207         final SessionIdProvider idProvider = new SessionIdProvider();
208
209         final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
210                 hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
211
212         final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
213                 serverNegotiatorFactory);
214         return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
215     }
216
217     protected HashedWheelTimer getHashedWheelTimer() {
218         return hashedWheelTimer;
219     }
220
221     protected EventLoopGroup getNettyThreadgroup() {
222         return nettyThreadgroup;
223     }
224
225     /**
226      * @After in subclasses is be called before this.
227      */
228     @After
229     public void cleanUpNetconf() throws Exception {
230         serverTcpChannel.close().await();
231         hashedWheelTimer.stop();
232         nettyThreadgroup.shutdownGracefully().await();
233     }
234
235     public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
236         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
237         b.withAddress(tcpAddress);
238         b.withSessionListener(new SimpleNetconfClientSessionListener());
239         b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
240         b.withConnectionTimeoutMillis(timeout);
241         return b.build();
242     }
243
244     public static final class HardcodedYangStoreService implements YangStoreService {
245
246         private final List<InputStream> byteArrayInputStreams;
247
248         public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws YangStoreException, IOException {
249             byteArrayInputStreams = new ArrayList<>();
250             for (final InputStream inputStream : inputStreams) {
251                 assertNotNull(inputStream);
252                 final byte[] content = IOUtils.toByteArray(inputStream);
253                 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
254                 byteArrayInputStreams.add(byteArrayInputStream);
255             }
256         }
257
258         @Override
259         public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException {
260             for (final InputStream inputStream : byteArrayInputStreams) {
261                 try {
262                     inputStream.reset();
263                 } catch (final IOException e) {
264                     throw new RuntimeException(e);
265                 }
266             }
267
268             final YangParserImpl yangParser = new YangParserImpl();
269             final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
270             final YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() {
271                 @Override
272                 public SchemaContext getSchemaContext() {
273                     return schemaContext ;
274                 }
275             });
276             return yangStoreService.getYangStoreSnapshot();
277         }
278     }
279 }