Integrate MRI projects for Neon
[netconf.git] / netconf / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / util / NetconfBaseOpsTest.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.netconf.sal.connect.netconf.util;
10
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.ArgumentMatchers.argThat;
13 import static org.mockito.ArgumentMatchers.eq;
14 import static org.mockito.Mockito.verify;
15 import static org.mockito.Mockito.when;
16
17 import com.google.common.base.Optional;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.InetSocketAddress;
21 import java.util.ArrayList;
22 import java.util.List;
23 import org.custommonkey.xmlunit.Diff;
24 import org.custommonkey.xmlunit.XMLUnit;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.ArgumentMatcher;
29 import org.mockito.Mock;
30 import org.mockito.MockitoAnnotations;
31 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
32 import org.opendaylight.netconf.api.NetconfMessage;
33 import org.opendaylight.netconf.api.xml.XmlUtil;
34 import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
35 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
36 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
37 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
38 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
39 import org.opendaylight.yangtools.yang.common.QName;
40 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
41 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
42 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
43 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
44 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
45 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
46 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
48 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
49 import org.w3c.dom.Document;
50 import org.w3c.dom.Element;
51 import org.w3c.dom.NamedNodeMap;
52 import org.xml.sax.SAXException;
53
54 public class NetconfBaseOpsTest {
55
56     static {
57         XMLUnit.setIgnoreWhitespace(true);
58         XMLUnit.setIgnoreComments(true);
59     }
60
61     private static final QName CONTAINER_Q_NAME = QName.create("test:namespace", "2013-07-22", "c");
62
63     @Mock
64     private RemoteDeviceCommunicator<NetconfMessage> listener;
65     private NetconfRpcFutureCallback callback;
66     private NetconfBaseOps baseOps;
67
68     @Before
69     public void setUp() throws Exception {
70         MockitoAnnotations.initMocks(this);
71         final InputStream okStream = getClass().getResourceAsStream("/netconfMessages/rpc-reply_ok.xml");
72         final InputStream dataStream = getClass().getResourceAsStream("/netconfMessages/rpc-reply_get.xml");
73         final NetconfMessage ok = new NetconfMessage(XmlUtil.readXmlToDocument(okStream));
74         final NetconfMessage data = new NetconfMessage(XmlUtil.readXmlToDocument(dataStream));
75         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME)))
76                 .thenReturn(RpcResultBuilder.success(data).buildFuture());
77         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_GET_QNAME)))
78                 .thenReturn(RpcResultBuilder.success(data).buildFuture());
79         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)))
80                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
81         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME)))
82                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
83         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME)))
84                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
85         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME)))
86                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
87         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)))
88                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
89         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)))
90                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
91         when(listener.sendRequest(any(), eq(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME)))
92                 .thenReturn(RpcResultBuilder.success(ok).buildFuture());
93         final SchemaContext schemaContext =
94                 YangParserTestUtils.parseYangResource("/schemas/test-module.yang");
95         final MessageTransformer<NetconfMessage> transformer = new NetconfMessageTransformer(schemaContext, true);
96         final DOMRpcService rpc = new NetconfDeviceRpc(schemaContext, listener, transformer);
97         final RemoteDeviceId id =
98                 new RemoteDeviceId("device-1", InetSocketAddress.createUnresolved("localhost", 17830));
99         callback = new NetconfRpcFutureCallback("prefix", id);
100         baseOps = new NetconfBaseOps(rpc, schemaContext);
101     }
102
103     @Test
104     public void testLock() throws Exception {
105         baseOps.lock(callback, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
106         verifyMessageSent("lock", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
107     }
108
109     @Test
110     public void testLockCandidate() throws Exception {
111         baseOps.lockCandidate(callback);
112         verifyMessageSent("lock", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
113     }
114
115     @Test
116     public void testUnlock() throws Exception {
117         baseOps.unlock(callback, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
118         verifyMessageSent("unlock", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
119     }
120
121     @Test
122     public void testUnlockCandidate() throws Exception {
123         baseOps.unlockCandidate(callback);
124         verifyMessageSent("unlock", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
125     }
126
127     @Test
128     public void testLockRunning() throws Exception {
129         baseOps.lockRunning(callback);
130         verifyMessageSent("lock-running", NetconfMessageTransformUtil.NETCONF_LOCK_QNAME);
131     }
132
133     @Test
134     public void testUnlockRunning() throws Exception {
135         baseOps.unlockRunning(callback);
136         verifyMessageSent("unlock-running", NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME);
137     }
138
139     @Test
140     public void testDiscardChanges() throws Exception {
141         baseOps.discardChanges(callback);
142         verifyMessageSent("discardChanges", NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME);
143     }
144
145     @Test
146     public void testCommit() throws Exception {
147         baseOps.commit(callback);
148         verifyMessageSent("commit", NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME);
149     }
150
151     @Test
152     public void testValidateCandidate() throws Exception {
153         baseOps.validateCandidate(callback);
154         verifyMessageSent("validate", NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME);
155     }
156
157     @Test
158     public void testValidateRunning() throws Exception {
159         baseOps.validateRunning(callback);
160         verifyMessageSent("validate-running", NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME);
161     }
162
163
164     @Test
165     public void testCopyConfig() throws Exception {
166         baseOps.copyConfig(callback, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME,
167                 NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME);
168         verifyMessageSent("copy-config", NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME);
169     }
170
171     @Test
172     public void testCopyRunningToCandidate() throws Exception {
173         baseOps.copyRunningToCandidate(callback);
174         verifyMessageSent("copy-config", NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME);
175     }
176
177
178     @Test
179     public void testGetConfigRunningData() throws Exception {
180         final Optional<NormalizedNode<?, ?>> dataOpt =
181                 baseOps.getConfigRunningData(callback, Optional.of(YangInstanceIdentifier.EMPTY)).get();
182         Assert.assertTrue(dataOpt.isPresent());
183         Assert.assertEquals(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataOpt.get().getNodeType());
184     }
185
186     @Test
187     public void testGetData() throws Exception {
188         final Optional<NormalizedNode<?, ?>> dataOpt =
189                 baseOps.getData(callback, Optional.of(YangInstanceIdentifier.EMPTY)).get();
190         Assert.assertTrue(dataOpt.isPresent());
191         Assert.assertEquals(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataOpt.get().getNodeType());
192     }
193
194     @Test
195     public void testGetConfigRunning() throws Exception {
196         baseOps.getConfigRunning(callback, Optional.absent());
197         verifyMessageSent("getConfig", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
198     }
199
200     @Test
201     public void testGetConfigCandidate() throws Exception {
202         baseOps.getConfigCandidate(callback, Optional.absent());
203         verifyMessageSent("getConfig_candidate", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
204     }
205
206     @Test
207     public void testGetConfigCandidateWithFilter() throws Exception {
208         final YangInstanceIdentifier id = YangInstanceIdentifier.builder()
209                 .node(CONTAINER_Q_NAME)
210                 .build();
211         baseOps.getConfigCandidate(callback, Optional.of(id));
212         verifyMessageSent("getConfig_candidate-filter", NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME);
213     }
214
215     @Test
216     public void testGet() throws Exception {
217         baseOps.get(callback, Optional.absent());
218         verifyMessageSent("get", NetconfMessageTransformUtil.NETCONF_GET_QNAME);
219     }
220
221     @Test
222     public void testEditConfigCandidate() throws Exception {
223         final QName leafQName = QName.create(CONTAINER_Q_NAME, "a");
224         final LeafNode<Object> leaf = Builders.leafBuilder()
225                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQName))
226                 .withValue("leaf-value")
227                 .build();
228         final YangInstanceIdentifier leafId = YangInstanceIdentifier.builder()
229                 .node(CONTAINER_Q_NAME)
230                 .node(leafQName)
231                 .build();
232         final DataContainerChild<?, ?> structure = baseOps.createEditConfigStrcture(Optional.of(leaf),
233                 Optional.of(ModifyAction.REPLACE), leafId);
234         baseOps.editConfigCandidate(callback, structure, true);
235         verifyMessageSent("edit-config-test-module", NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME);
236     }
237
238     @Test
239     public void testEditConfigRunning() throws Exception {
240         final QName containerQName = QName.create("test:namespace", "2013-07-22", "c");
241         final QName leafQName = QName.create(containerQName, "a");
242         final LeafNode<Object> leaf = Builders.leafBuilder()
243                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQName))
244                 .withValue("leaf-value")
245                 .build();
246         final YangInstanceIdentifier leafId = YangInstanceIdentifier.builder()
247                 .node(containerQName)
248                 .node(leafQName)
249                 .build();
250         final DataContainerChild<?, ?> structure = baseOps.createEditConfigStrcture(Optional.of(leaf),
251                 Optional.of(ModifyAction.REPLACE), leafId);
252         baseOps.editConfigRunning(callback, structure, ModifyAction.MERGE, true);
253         verifyMessageSent("edit-config-test-module-running", NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME);
254     }
255
256     private void verifyMessageSent(final String fileName, final QName name) {
257         final String path = "/netconfMessages/" + fileName + ".xml";
258         verify(listener).sendRequest(msg(path), eq(name));
259     }
260
261     private static NetconfMessage msg(final String name) {
262         final InputStream stream = NetconfBaseOpsTest.class.getResourceAsStream(name);
263         try {
264             return argThat(new NetconfMessageMatcher(XmlUtil.readXmlToDocument(stream)));
265         } catch (SAXException | IOException e) {
266             throw new IllegalStateException("Failed to read xml file " + name, e);
267         }
268     }
269
270     private static class NetconfMessageMatcher implements ArgumentMatcher<NetconfMessage> {
271
272         private final Document expected;
273
274         NetconfMessageMatcher(final Document expected) {
275             this.expected = removeAttrs(expected);
276         }
277
278         @Override
279         public boolean matches(final NetconfMessage message) {
280             final Document actualDoc = removeAttrs(message.getDocument());
281             actualDoc.normalizeDocument();
282             expected.normalizeDocument();
283             final Diff diff = XMLUnit.compareXML(expected, actualDoc);
284             return diff.similar();
285         }
286
287         private static Document removeAttrs(final Document input) {
288             final Document copy = XmlUtil.newDocument();
289             copy.appendChild(copy.importNode(input.getDocumentElement(), true));
290             final Element element = copy.getDocumentElement();
291             final List<String> attrNames = new ArrayList<>();
292             final NamedNodeMap attributes = element.getAttributes();
293             for (int i = 0; i < attributes.getLength(); i++) {
294                 final String nodeName = attributes.item(i).getNodeName();
295                 if ("xmlns".equals(nodeName)) {
296                     continue;
297                 }
298                 attrNames.add(nodeName);
299             }
300             attrNames.forEach(element::removeAttribute);
301             return copy;
302         }
303     }
304
305 }