BUG-2453 (De)Serialize enum values as defined in yang
[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.mock;
17 import com.google.common.io.ByteStreams;
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelFuture;
20 import io.netty.channel.EventLoopGroup;
21 import io.netty.channel.local.LocalAddress;
22 import io.netty.channel.nio.NioEventLoopGroup;
23 import io.netty.util.HashedWheelTimer;
24 import io.netty.util.concurrent.GlobalEventExecutor;
25 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.net.InetSocketAddress;
29 import java.net.SocketAddress;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.concurrent.TimeUnit;
37 import org.junit.After;
38 import org.junit.Before;
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.controller.netconf.api.NetconfMessage;
48 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
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.EnumResolver;
54 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
55 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
56 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
57 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl;
58 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
59 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
60 import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
61 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
62 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
63 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
64 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
65 import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener;
66 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
67 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange;
69 import org.opendaylight.yangtools.yang.binding.BindingMapping;
70 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
71 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
72 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
73 import org.w3c.dom.Element;
74
75 public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
76
77     public static final String LOOPBACK_ADDRESS = "127.0.0.1";
78     public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
79     private static final int RESOURCE_TIMEOUT_MINUTES = 2;
80
81     static ModuleFactory[] FACTORIES = {new TestImplModuleFactory(),
82                                         new DepTestImplModuleFactory(),
83                                         new NetconfTestImplModuleFactory(),
84                                         new IdentityTestModuleFactory(),
85                                         new MultipleDependenciesModuleFactory() };
86
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 = new AggregatedNetconfOperationServiceFactory();
111         final NetconfMonitoringService netconfMonitoringService = getNetconfMonitoringService(factoriesListener);
112         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
113         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(new NetconfMonitoringOperationService(netconfMonitoringService)));
114
115         for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories(factoriesListener)) {
116             factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
117         }
118
119         serverTcpChannel = startNetconfTcpServer(factoriesListener, netconfMonitoringService);
120         clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
121     }
122
123     /**
124      * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
125      */
126     protected void setUpTestInitial() throws Exception {}
127
128     private void loadMessages() throws Exception {
129         this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
130         this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
131     }
132
133     public NetconfMessage getGetConfig() {
134         return getConfig;
135     }
136
137     public NetconfMessage getGet() {
138         return get;
139     }
140
141     private Channel startNetconfTcpServer(final AggregatedNetconfOperationServiceFactory listener, final NetconfMonitoringService monitoring) throws Exception {
142         final NetconfServerDispatcherImpl dispatch = createDispatcher(listener, monitoring, getNotificationProducer());
143
144         final ChannelFuture s;
145         if(getTcpServerAddress() instanceof LocalAddress) {
146             s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
147         } else {
148             s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
149         }
150         s.await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
151         return s.channel();
152     }
153
154     protected DefaultCommitNotificationProducer getNotificationProducer() {
155         final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
156         doNothing().when(notificationProducer).close();
157         doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
158         return notificationProducer;
159     }
160
161     protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
162         return Collections.emptySet();
163     }
164
165     protected NetconfMonitoringService getNetconfMonitoringService(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
166         return new NetconfMonitoringServiceImpl(factoriesListener);
167     }
168
169     protected abstract SocketAddress getTcpServerAddress();
170
171     public NetconfClientDispatcherImpl getClientDispatcher() {
172         return clientDispatcher;
173     }
174
175     private HardcodedYangStoreService getYangStore() throws 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/test-groups.yang",
189                 "/META-INF/yang/ietf-inet-types.yang");
190
191         final Collection<InputStream> yangDependencies = new ArrayList<>();
192         final List<String> failedToFind = new ArrayList<>();
193         for (final String path : paths) {
194             final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
195             if (resourceAsStream == null) {
196                 failedToFind.add(path);
197             } else {
198                 yangDependencies.add(resourceAsStream);
199             }
200         }
201         assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
202         return yangDependencies;
203     }
204
205     protected NetconfServerDispatcherImpl createDispatcher(
206             final AggregatedNetconfOperationServiceFactory factoriesListener, final NetconfMonitoringService sessionMonitoringService,
207             final DefaultCommitNotificationProducer commitNotifier) {
208         final SessionIdProvider idProvider = new SessionIdProvider();
209
210         final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
211                 hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
212
213         final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer(
214                 serverNegotiatorFactory);
215         return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
216     }
217
218     protected HashedWheelTimer getHashedWheelTimer() {
219         return hashedWheelTimer;
220     }
221
222     protected EventLoopGroup getNettyThreadgroup() {
223         return nettyThreadgroup;
224     }
225
226     /**
227      * @After in subclasses is be called before this.
228      */
229     @After
230     public void cleanUpNetconf() throws Exception {
231         serverTcpChannel.close().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
232         hashedWheelTimer.stop();
233         nettyThreadgroup.shutdownGracefully().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
234     }
235
236     public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
237         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
238         b.withAddress(tcpAddress);
239         b.withSessionListener(new SimpleNetconfClientSessionListener());
240         b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
241         b.withConnectionTimeoutMillis(timeout);
242         return b.build();
243     }
244
245     public static final class HardcodedYangStoreService extends YangStoreService {
246         public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws IOException {
247             super(new SchemaContextProvider() {
248                 @Override
249                 public SchemaContext getSchemaContext() {
250                     return getSchema(inputStreams);
251                 }
252             }, new BaseNetconfNotificationListener() {
253                 @Override
254                 public void onCapabilityChanged(final NetconfCapabilityChange capabilityChange) {
255                     // NOOP
256                 }
257             });
258         }
259
260         private static SchemaContext getSchema(final Collection<? extends InputStream> inputStreams) {
261             final ArrayList<InputStream> byteArrayInputStreams = new ArrayList<>();
262             for (final InputStream inputStream : inputStreams) {
263                 assertNotNull(inputStream);
264                 final byte[] content;
265                 try {
266                     content = ByteStreams.toByteArray(inputStream);
267                 } catch (IOException e) {
268                     throw new IllegalStateException("Cannot read " + inputStream, e);
269                 }
270                 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
271                 byteArrayInputStreams.add(byteArrayInputStream);
272             }
273
274             for (final InputStream inputStream : byteArrayInputStreams) {
275                 try {
276                     inputStream.reset();
277                 } catch (final IOException e) {
278                     throw new RuntimeException(e);
279                 }
280             }
281
282             final YangParserImpl yangParser = new YangParserImpl();
283             return yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
284         }
285
286         @Override
287         public EnumResolver getEnumResolver() {
288             return new EnumResolver() {
289                 @Override
290                 public String fromYang(final String enumType, final String enumYangValue) {
291                     return BindingMapping.getClassName(enumYangValue);
292                 }
293
294                 @Override
295                 public String toYang(final String enumType, final String enumJavaValue) {
296                     return enumJavaValue.toLowerCase();
297                 }
298             };
299         }
300     }
301 }