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