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