Add configurable connection timeout to netconf client.
[controller.git] / opendaylight / netconf / netconf-it / src / test / java / org / opendaylight / controller / netconf / it / NetconfConfigPersisterITTest.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 com.google.common.collect.Lists;
11 import com.google.common.collect.Sets;
12 import io.netty.channel.ChannelFuture;
13 import org.apache.commons.lang3.StringUtils;
14 import org.junit.After;
15 import org.junit.Assert;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.junit.matchers.JUnitMatchers;
19 import org.mockito.invocation.InvocationOnMock;
20 import org.mockito.stubbing.Answer;
21 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
22 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
23 import org.opendaylight.controller.config.persist.api.Persister;
24 import org.opendaylight.controller.config.spi.ModuleFactory;
25 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
26 import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
27 import org.opendaylight.controller.netconf.api.NetconfMessage;
28 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
29 import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
30 import org.opendaylight.controller.netconf.client.NetconfClient;
31 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
32 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
33 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
34 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
35 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
36 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
37 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
38 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
39 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
40 import org.opendaylight.controller.netconf.mapping.api.Capability;
41 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
42 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
43 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
44 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
45 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
46 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.w3c.dom.Element;
50
51 import javax.management.InstanceNotFoundException;
52 import javax.management.Notification;
53 import javax.management.NotificationListener;
54 import java.io.IOException;
55 import java.io.InputStream;
56 import java.net.InetSocketAddress;
57 import java.util.Collection;
58 import java.util.List;
59 import java.util.Set;
60 import java.util.regex.Pattern;
61
62 import static junit.framework.Assert.assertEquals;
63 import static org.mockito.Matchers.any;
64 import static org.mockito.Matchers.anyLong;
65 import static org.mockito.Mockito.doAnswer;
66 import static org.mockito.Mockito.doNothing;
67 import static org.mockito.Mockito.doReturn;
68 import static org.mockito.Mockito.mock;
69
70 public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
71
72     private static final Logger logger =  LoggerFactory.getLogger(NetconfConfigPersisterITTest.class);
73
74     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
75
76
77
78     private NetconfClientDispatcher clientDispatcher;
79
80     DefaultCommitNotificationProducer commitNotifier;
81
82     @Before
83     public void setUp() throws Exception {
84         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
85                 new ModuleFactory[0])));
86
87         NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getFactoriesListener());
88
89         NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
90         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
91         factoriesListener
92                 .onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
93                         new NetconfMonitoringOperationService(monitoringService)));
94
95
96         commitNotifier = new DefaultCommitNotificationProducer(platformMBeanServer);
97         NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, mockSessionMonitoringService(), commitNotifier);
98         ChannelFuture s = dispatch.createServer(tcpAddress);
99         s.await();
100
101         clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, 5000);
102     }
103
104     @After
105     public void cleanUp(){
106         commitNotifier.close();
107     }
108
109     private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
110         final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
111         return new HardcodedYangStoreService(yangDependencies);
112     }
113
114
115     protected SessionMonitoringService mockSessionMonitoringService() {
116         SessionMonitoringService mockedSessionMonitor = mock(SessionMonitoringService.class);
117         doNothing().when(mockedSessionMonitor).onSessionUp(any(NetconfManagementSession.class));
118         doNothing().when(mockedSessionMonitor).onSessionDown(any(NetconfManagementSession.class));
119         return mockedSessionMonitor;
120     }
121
122
123
124     @Test
125     public void testNetconfCommitNotifications() throws Exception {
126
127         VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
128         VerifyingPersister mockedAggregator = mockAggregator();
129
130         try (NetconfClient persisterClient = new NetconfClient("persister", tcpAddress, 4000, clientDispatcher)) {
131             ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(
132                     platformMBeanServer, persisterClient, mockedAggregator,
133                     Pattern.compile(""));
134             configPersisterNotificationHandler.init();
135
136             try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) {
137                 NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage());
138                 assertResponse(response, "<modules");
139                 assertResponse(response, "<services");
140                 response = netconfClient.sendMessage(loadCommitMessage());
141                 assertResponse(response, "ok");
142
143                 response = netconfClient.sendMessage(loadEditConfigMessage());
144                 assertResponse(response, "ok");
145                 response = netconfClient.sendMessage(loadCommitMessage());
146                 assertResponse(response, "ok");
147             }
148         }
149
150         notificationVerifier.assertNotificationCount(2);
151         notificationVerifier.assertNotificationContent(0, 0, 0, 9);
152         notificationVerifier.assertNotificationContent(1, 4, 4, 9);
153
154         mockedAggregator.assertSnapshotCount(2);
155         // Capabilities are stripped for persister
156         mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
157         mockedAggregator.assertSnapshotContent(1, 4, 4, 3);
158     }
159
160     private VerifyingPersister mockAggregator() throws IOException {
161         return new VerifyingPersister();
162     }
163
164     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
165         VerifyingNotificationListener listener = new VerifyingNotificationListener();
166         platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.objectName, listener, null, null);
167         return listener;
168     }
169
170     private void assertResponse(NetconfMessage response, String content) {
171         Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString(content));
172     }
173
174     private NetconfMessage loadGetConfigMessage() throws Exception {
175         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
176     }
177
178     private NetconfMessage loadEditConfigMessage() throws Exception {
179         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig.xml");
180     }
181
182     private NetconfMessage loadCommitMessage() throws Exception {
183         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
184     }
185
186
187     public NetconfOperationServiceFactoryListener getFactoriesListener() {
188         NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class);
189         NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class);
190         NetconfOperationService service = mock(NetconfOperationService.class);
191         Set<Capability> caps = Sets.newHashSet();
192         doReturn(caps).when(service).getCapabilities();
193         Set<NetconfOperationService> services = Sets.newHashSet(service);
194         doReturn(services).when(snap).getServices();
195         doReturn(snap).when(factoriesListener).getSnapshot(anyLong());
196
197         return factoriesListener;
198     }
199
200     private static class VerifyingNotificationListener implements NotificationListener {
201         public List<Notification> notifications = Lists.newArrayList();
202
203         @Override
204         public void handleNotification(Notification notification, Object handback) {
205             this.notifications.add(notification);
206         }
207
208         void assertNotificationCount(Object size) {
209             assertEquals(size, notifications.size());
210         }
211
212         void assertNotificationContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
213             Notification notification = notifications.get(notificationIndex);
214             assertEquals(CommitJMXNotification.class, notification.getClass());
215             int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
216             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
217             Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
218             int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
219             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
220             int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
221             assertEquals("Expected services count", expectedServicesSize, servicesSize);
222         }
223     }
224
225     private static class VerifyingPersister implements Persister {
226
227         public List<ConfigSnapshotHolder> snapshots = Lists.newArrayList();
228         private Persister mockedPersister;
229
230         public VerifyingPersister() throws IOException {
231             Persister mockedAggregator = mock(Persister.class);
232
233             doAnswer(new Answer() {
234                 @Override
235                 public Object answer(InvocationOnMock invocation) throws Throwable {
236                     ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
237                     snapshots.add(configSnapshot);
238                     return null;
239                 }
240             }).when(mockedAggregator).persistConfig(any(ConfigSnapshotHolder.class));
241
242             this.mockedPersister = mockedAggregator;
243         }
244
245         void assertSnapshotCount(Object size) {
246             assertEquals(size, snapshots.size());
247         }
248
249         void assertSnapshotContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
250             ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
251             int capsSize = snapshot.getCapabilities().size();
252             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
253             String configSnapshot = snapshot.getConfigSnapshot();
254             int modulesSize = StringUtils.countMatches(configSnapshot, "<module>");
255             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
256             int servicesSize = StringUtils.countMatches(configSnapshot, "<instance>");
257             assertEquals("Expected services count", expectedServicesSize, servicesSize);
258         }
259
260         @Override
261         public void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException {
262             mockedPersister.persistConfig(configSnapshotHolder);
263         }
264
265         @Override
266         public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
267             return mockedPersister.loadLastConfigs();
268         }
269
270         @Override
271         public void close() {
272             mockedPersister.close();
273         }
274     }
275 }