BUG 1853 : Clustered Data Store causes Out of Memory
[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 static junit.framework.Assert.assertEquals;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.anyString;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithName;
17 import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertElementsCount;
18 import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToDocument;
19
20 import com.google.common.collect.Lists;
21 import com.google.common.collect.Sets;
22 import java.io.IOException;
23 import java.lang.management.ManagementFactory;
24 import java.net.InetSocketAddress;
25 import java.net.SocketAddress;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Set;
29 import javax.management.InstanceNotFoundException;
30 import javax.management.Notification;
31 import javax.management.NotificationListener;
32 import org.junit.Test;
33 import org.mockito.invocation.InvocationOnMock;
34 import org.mockito.stubbing.Answer;
35 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
36 import org.opendaylight.controller.config.persist.api.Persister;
37 import org.opendaylight.controller.netconf.api.NetconfMessage;
38 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
39 import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
40 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
41 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
42 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
43 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
44 import org.opendaylight.controller.netconf.mapping.api.Capability;
45 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
46 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
47 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
48 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
49 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
50 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
51 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
54 import org.xml.sax.SAXException;
55
56 public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
57
58     public static final int PORT = 12026;
59     private static final InetSocketAddress TCP_ADDRESS = new InetSocketAddress(LOOPBACK_ADDRESS, PORT);
60
61     private NetconfMonitoringServiceImpl netconfMonitoringService;
62
63     @Override
64     protected void setUpTestInitial() {
65         netconfMonitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
66     }
67
68     @Override
69     protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
70         return netconfMonitoringService;
71     }
72
73     @Override
74     protected SocketAddress getTcpServerAddress() {
75         return TCP_ADDRESS;
76     }
77
78     @Override
79     protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
80         return Collections.<NetconfOperationServiceFactory>singletonList(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
81                 new NetconfMonitoringOperationService(netconfMonitoringService)));
82     }
83
84     @Override
85     protected DefaultCommitNotificationProducer getNotificationProducer() {
86         return new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
87     }
88
89     @Test
90     public void testNetconfCommitNotifications() throws Exception {
91         final VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
92         final VerifyingPersister mockedAggregator = mockAggregator();
93
94         try (TestingNetconfClient persisterClient = new TestingNetconfClient("persister", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 4000))) {
95             try (ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(
96                     platformMBeanServer, mockedAggregator)) {
97
98
99                 try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", getClientDispatcher(), getClientConfiguration(TCP_ADDRESS, 4000))) {
100                     NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage());
101                     assertContainsElementWithName(response.getDocument(), "modules");
102                     assertContainsElementWithName(response.getDocument(), "services");
103                     response = netconfClient.sendMessage(loadCommitMessage());
104                     assertContainsElementWithName(response.getDocument(), "ok");
105
106                     response = netconfClient.sendMessage(loadEditConfigMessage());
107                     assertContainsElementWithName(response.getDocument(), "ok");
108                     response = netconfClient.sendMessage(loadCommitMessage());
109                     assertContainsElementWithName(response.getDocument(), "ok");
110                 }
111             }
112         }
113
114         notificationVerifier.assertNotificationCount(2);
115         notificationVerifier.assertNotificationContent(0, 0, 0, 8);
116         notificationVerifier.assertNotificationContent(1, 4, 3, 8);
117
118         mockedAggregator.assertSnapshotCount(2);
119         // Capabilities are stripped for persister
120         mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
121         mockedAggregator.assertSnapshotContent(1, 4, 3, 3);
122     }
123
124     private VerifyingPersister mockAggregator() throws IOException {
125         return new VerifyingPersister();
126     }
127
128     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
129         final VerifyingNotificationListener listener = new VerifyingNotificationListener();
130         platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.OBJECT_NAME, listener, null, null);
131         return listener;
132     }
133
134     private NetconfMessage loadGetConfigMessage() throws Exception {
135         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
136     }
137
138     private NetconfMessage loadEditConfigMessage() throws Exception {
139         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig.xml");
140     }
141
142     private NetconfMessage loadCommitMessage() throws Exception {
143         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
144     }
145
146
147     public NetconfOperationProvider getNetconfOperationProvider() {
148         final NetconfOperationProvider factoriesListener = mock(NetconfOperationProvider.class);
149         final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
150         final NetconfOperationService service = mock(NetconfOperationService.class);
151         final Set<Capability> caps = Sets.newHashSet();
152         doReturn(caps).when(service).getCapabilities();
153         final Set<NetconfOperationService> services = Sets.newHashSet(service);
154         doReturn(services).when(snap).getServices();
155         doReturn(snap).when(factoriesListener).openSnapshot(anyString());
156
157         return factoriesListener;
158     }
159
160     private static class VerifyingNotificationListener implements NotificationListener {
161         public List<Notification> notifications = Lists.newArrayList();
162
163         @Override
164         public void handleNotification(final Notification notification, final Object handback) {
165             this.notifications.add(notification);
166         }
167
168         void assertNotificationCount(final Object size) {
169             assertEquals(size, notifications.size());
170         }
171
172         void assertNotificationContent(final int notificationIndex, final int expectedModulesSize, final int expectedServicesSize, final int expectedCapsSize) {
173             final Notification notification = notifications.get(notificationIndex);
174             assertEquals(CommitJMXNotification.class, notification.getClass());
175             final int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
176             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
177             final Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
178             final int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
179             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
180             final int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
181             assertEquals("Expected services count", expectedServicesSize, servicesSize);
182         }
183     }
184
185     private static class VerifyingPersister implements Persister {
186
187         public List<ConfigSnapshotHolder> snapshots = Lists.newArrayList();
188         private Persister mockedPersister;
189
190         public VerifyingPersister() throws IOException {
191             final Persister mockedAggregator = mock(Persister.class);
192
193             doAnswer(new Answer<Object>() {
194                 @Override
195                 public Object answer(final InvocationOnMock invocation) throws Throwable {
196                     final ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
197                     snapshots.add(configSnapshot);
198                     return null;
199                 }
200             }).when(mockedAggregator).persistConfig(any(ConfigSnapshotHolder.class));
201
202             this.mockedPersister = mockedAggregator;
203         }
204
205         void assertSnapshotCount(final Object size) {
206             assertEquals(size, snapshots.size());
207         }
208
209         void assertSnapshotContent(final int notificationIndex, final int expectedModulesSize, final int expectedServicesSize, final int expectedCapsSize)
210                 throws SAXException, IOException {
211             final ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
212             final int capsSize = snapshot.getCapabilities().size();
213             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
214             final Document configSnapshot = readXmlToDocument(snapshot.getConfigSnapshot());
215             assertElementsCount(configSnapshot, "module", expectedModulesSize);
216             assertElementsCount(configSnapshot, "instance", expectedServicesSize);
217         }
218
219         @Override
220         public void persistConfig(final ConfigSnapshotHolder configSnapshotHolder) throws IOException {
221             mockedPersister.persistConfig(configSnapshotHolder);
222         }
223
224         @Override
225         public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
226             return mockedPersister.loadLastConfigs();
227         }
228
229         @Override
230         public void close() {
231             mockedPersister.close();
232         }
233     }
234 }