NETCONF-557: Add support for URL capability
[netconf.git] / netconf / mdsal-netconf-connector / src / test / java / org / opendaylight / netconf / mdsal / connector / ops / CopyConfigTest.java
1 /*
2  * Copyright (c) 2018 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.mdsal.connector.ops;
10
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13 import static org.opendaylight.yangtools.yang.test.util.YangParserTestUtils.parseYangResources;
14
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.net.MalformedURLException;
18 import java.net.URI;
19 import org.junit.Rule;
20 import org.junit.Test;
21 import org.junit.rules.TemporaryFolder;
22 import org.opendaylight.netconf.api.DocumentedException;
23 import org.opendaylight.netconf.api.DocumentedException.ErrorSeverity;
24 import org.opendaylight.netconf.api.DocumentedException.ErrorTag;
25 import org.opendaylight.netconf.api.DocumentedException.ErrorType;
26 import org.opendaylight.netconf.api.xml.XmlUtil;
27 import org.opendaylight.netconf.util.test.XmlFileLoader;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 import org.w3c.dom.Document;
30 import org.xml.sax.SAXException;
31
32 public class CopyConfigTest extends AbstractNetconfOperationTest {
33     @Rule
34     public TemporaryFolder tmpDir = new TemporaryFolder();
35
36     @Override
37     protected SchemaContext getSchemaContext() {
38         return parseYangResources(CopyConfigTest.class,
39             "/yang/mdsal-netconf-mapping-test.yang");
40     }
41
42
43     @Test
44     public void testTargetMissing() throws Exception {
45         try {
46             copyConfig("messages/mapping/copyConfigs/copyConfig_no_target.xml");
47             fail("Should have failed - <target> element is missing");
48         } catch (final DocumentedException e) {
49             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
50             assertTrue(e.getErrorTag() == ErrorTag.MISSING_ATTRIBUTE);
51             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
52         }
53     }
54
55     @Test
56     public void testSourceMissing() throws Exception {
57         try {
58             copyConfig("messages/mapping/copyConfigs/copyConfig_no_source.xml");
59             fail("Should have fanode1iled - <source> element is missing");
60         } catch (final DocumentedException e) {
61             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
62             assertTrue(e.getErrorTag() == ErrorTag.MISSING_ELEMENT);
63             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
64         }
65     }
66
67     @Test
68     public void testConfigMissing() throws Exception {
69         try {
70             copyConfig("messages/mapping/copyConfigs/copyConfig_no_config.xml");
71             fail("Should have failed - neither <config> nor <url> element is present");
72         } catch (final DocumentedException e) {
73             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
74             assertTrue(e.getErrorTag() == ErrorTag.MISSING_ELEMENT);
75             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
76         }
77     }
78
79     @Test
80     public void testRunning() throws Exception {
81         try {
82             copyConfig("messages/mapping/copyConfigs/copyConfig_running.xml");
83             fail("Should have failed - copy config on running datastore is not supported");
84         } catch (final DocumentedException e) {
85             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
86             assertTrue(e.getErrorTag() == ErrorTag.OPERATION_NOT_SUPPORTED);
87             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
88         }
89     }
90
91     @Test
92     public void testCandidateTransaction() throws Exception {
93         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_top_modules.xml"), RPC_REPLY_OK);
94         verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument(
95             "messages/mapping/copyConfigs/copyConfig_top_modules_control.xml"));
96         assertEmptyDatastore(getConfigRunning());
97
98         verifyResponse(discardChanges(), RPC_REPLY_OK);
99         assertEmptyDatastore(getConfigCandidate());
100     }
101
102     @Test
103     public void testWithCommit() throws Exception {
104         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_top_modules.xml"), RPC_REPLY_OK);
105         final Document expectedConfig = XmlFileLoader.xmlFileToDocument(
106             "messages/mapping/copyConfigs/copyConfig_top_modules_control.xml");
107         verifyResponse(getConfigCandidate(), expectedConfig);
108
109         verifyResponse(commit(), RPC_REPLY_OK);
110         verifyResponse(getConfigRunning(), expectedConfig);
111     }
112
113     @Test
114     public void testDeleteSubtree() throws Exception {
115         // Initialize datastore
116         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_delete_setup.xml"), RPC_REPLY_OK);
117         verifyResponse(commit(), RPC_REPLY_OK);
118         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
119             "messages/mapping/copyConfigs/copyConfig_delete_setup_control.xml"));
120
121         // Issue second copy-config, this time without top container
122         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_delete.xml"), RPC_REPLY_OK);
123         verifyResponse(commit(), RPC_REPLY_OK);
124         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
125             "messages/mapping/copyConfigs/copyConfig_delete_control.xml"));
126     }
127
128     @Test
129     public void testList() throws Exception {
130         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_list_setup.xml"), RPC_REPLY_OK);
131         verifyResponse(commit(), RPC_REPLY_OK);
132         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
133             "messages/mapping/copyConfigs/copyConfig_list_setup_control.xml"));
134
135         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_list_update.xml"), RPC_REPLY_OK);
136         verifyResponse(commit(), RPC_REPLY_OK);
137         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
138             "messages/mapping/copyConfigs/copyConfig_list_update_control.xml"));
139     }
140
141     @Test
142     public void testOrderedList() throws Exception {
143         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_ordered_list_setup.xml"),
144             RPC_REPLY_OK);
145         verifyResponse(commit(), RPC_REPLY_OK);
146         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
147             "messages/mapping/copyConfigs/copyConfig_ordered_list_setup_control.xml"));
148
149         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_ordered_list_update.xml"),
150             RPC_REPLY_OK);
151         verifyResponse(commit(), RPC_REPLY_OK);
152         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
153             "messages/mapping/copyConfigs/copyConfig_ordered_list_update_control.xml"));
154     }
155
156     @Test
157     public void testToplevelList() throws Exception {
158         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_toplevel_list_setup.xml"),
159             RPC_REPLY_OK);
160         verifyResponse(commit(), RPC_REPLY_OK);
161         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
162             "messages/mapping/copyConfigs/copyConfig_toplevel_list_setup_control.xml"));
163
164         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_toplevel_list_update.xml"),
165             RPC_REPLY_OK);
166         verifyResponse(commit(), RPC_REPLY_OK);
167         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
168             "messages/mapping/copyConfigs/copyConfig_toplevel_list_update_control.xml"));
169     }
170
171     @Test
172     public void testEmptyContainer() throws Exception {
173         // Check that empty non-presence container is removed.
174         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_empty_container.xml"),
175             RPC_REPLY_OK);
176         verifyResponse(commit(), RPC_REPLY_OK);
177         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
178             "messages/mapping/copyConfigs/copyConfig_empty_container_control.xml"));
179     }
180
181     @Test
182     public void testEmptyPresenceContainer() throws Exception {
183         // Check that empty presence container is not removed.
184         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_empty_presence_container.xml"),
185             RPC_REPLY_OK);
186         verifyResponse(commit(), RPC_REPLY_OK);
187         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
188             "messages/mapping/copyConfigs/copyConfig_empty_presence_container_control.xml"));
189     }
190
191     @Test
192     public void testAugmentations() throws Exception {
193         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_top_augmentation.xml"),
194             RPC_REPLY_OK);
195         verifyResponse(commit(), RPC_REPLY_OK);
196         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
197             "messages/mapping/copyConfigs/copyConfig_top_augmentation_control.xml"));
198     }
199
200     @Test
201     public void testChoices() throws Exception {
202         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_choices1.xml"), RPC_REPLY_OK);
203         verifyResponse(commit(), RPC_REPLY_OK);
204         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_choices2.xml"), RPC_REPLY_OK);
205         verifyResponse(commit(), RPC_REPLY_OK);
206         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_choices3.xml"), RPC_REPLY_OK);
207         verifyResponse(commit(), RPC_REPLY_OK);
208         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_choices4.xml"), RPC_REPLY_OK);
209         verifyResponse(commit(), RPC_REPLY_OK);
210         verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument(
211             "messages/mapping/copyConfigs/copyConfig_choices_control.xml"));
212     }
213
214     @Test
215     public void testConfigFromFile() throws Exception {
216         // Ask class loader for URI of config file and use it as <url> in <copy-config> RPC:
217         final String template = XmlFileLoader.fileToString("messages/mapping/copyConfigs/copyConfig_from_file.xml");
218         final URI uri = getClass().getClassLoader()
219             .getResource("messages/mapping/copyConfigs/config_file_valid.xml").toURI();
220         final String copyConfig = template.replaceFirst("URL", uri.toString());
221         final Document request = XmlUtil.readXmlToDocument(copyConfig);
222
223         verifyResponse(copyConfig(request), RPC_REPLY_OK);
224         verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument(
225             "messages/mapping/copyConfigs/copyConfig_from_file_control.xml"));
226     }
227
228     @Test
229     public void testConfigFromInvalidUrl() throws Exception {
230         try {
231             copyConfig("messages/mapping/copyConfigs/copyConfig_invalid_url.xml");
232             fail("Should have failed - provided <url> is not valid");
233         } catch (final DocumentedException e) {
234             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
235             assertTrue(e.getErrorTag() == ErrorTag.INVALID_VALUE);
236             assertTrue(e.getErrorType() == ErrorType.APPLICATION);
237             assertTrue(e.getCause() instanceof MalformedURLException);
238         }
239     }
240
241     @Test
242     public void testExternalConfigInvalid() throws Exception {
243         try {
244             // Ask class loader for URI of config file and use it as <url> in <copy-config> RPC:
245             final String template = XmlFileLoader.fileToString("messages/mapping/copyConfigs/copyConfig_from_file.xml");
246             final URI uri = getClass().getClassLoader()
247                 .getResource("messages/mapping/copyConfigs/config_file_invalid.xml").toURI();
248             final String copyConfig = template.replaceFirst("URL", uri.toString());
249             final Document request = XmlUtil.readXmlToDocument(copyConfig);
250             copyConfig(request);
251             fail("Should have failed - provided config is not valid XML");
252         } catch (final DocumentedException e) {
253             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
254             assertTrue(e.getErrorTag() == ErrorTag.OPERATION_FAILED);
255             assertTrue(e.getErrorType() == ErrorType.APPLICATION);
256             assertTrue(e.getCause() instanceof SAXException);
257         }
258     }
259
260     @Test
261     public void testCopyToFile() throws Exception {
262         // Initialize config:
263         verifyResponse(copyConfig("messages/mapping/copyConfigs/copyConfig_top_modules.xml"), RPC_REPLY_OK);
264         verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument(
265             "messages/mapping/copyConfigs/copyConfig_top_modules_control.xml"));
266
267         // Load copy-config template and replace URL with the URI of target file:
268         final String template = XmlFileLoader.fileToString("messages/mapping/copyConfigs/copyConfig_to_file.xml");
269         final File outFile = new File(tmpDir.getRoot(),"test-copy-to-file.xml");
270         final String copyConfig = template.replaceFirst("URL", outFile.toURI().toString());
271         final Document request = XmlUtil.readXmlToDocument(copyConfig);
272
273         // Invoke copy-config RPC:
274         verifyResponse(copyConfig(request), RPC_REPLY_OK);
275
276         // Check if outFile was created with expected content:
277         verifyResponse(XmlUtil.readXmlToDocument(new FileInputStream(outFile)),
278             XmlFileLoader.xmlFileToDocument("messages/mapping/copyConfigs/copyConfig_to_file_control.xml"));
279     }
280
281     @Test
282     public void testUnsupportedTargetUrlProtocol() throws Exception {
283         try {
284             copyConfig("messages/mapping/copyConfigs/copyConfig_to_unsupported_url_protocol.xml");
285             fail("Should have failed - exporting config to http server is not supported");
286         } catch (final DocumentedException e) {
287             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
288             assertTrue(e.getErrorTag() == ErrorTag.OPERATION_NOT_SUPPORTED);
289             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
290         }
291     }
292
293     @Test
294     public void testCopyToFileFromRunning() throws Exception {
295         // Load copy-config template and replace URL with the URI of target file:
296         final String template =
297             XmlFileLoader.fileToString("messages/mapping/copyConfigs/copyConfig_to_file_from_running.xml");
298         final File outFile = new File(tmpDir.getRoot(),"test-copy-to-file-from-running.xml");
299         final String copyConfig = template.replaceFirst("URL", outFile.toURI().toString());
300         final Document request = XmlUtil.readXmlToDocument(copyConfig);
301
302         // Invoke copy-config RPC:
303         verifyResponse(copyConfig(request), RPC_REPLY_OK);
304
305         // Check if outFile was created with expected content:
306         verifyResponse(XmlUtil.readXmlToDocument(new FileInputStream(outFile)),
307             XmlFileLoader.xmlFileToDocument(
308                 "messages/mapping/copyConfigs/copyConfig_to_file_from_running_control.xml"));
309
310     }
311
312     @Test
313     public void testRemoteToRemoteOperationIsNotSupported() throws Exception {
314         try {
315             copyConfig("messages/mapping/copyConfigs/copyConfig_url_remote_to_remote.xml");
316             fail("Should have failed - remote to remote operations are not supported");
317         } catch (final DocumentedException e) {
318             assertTrue(e.getErrorSeverity() == ErrorSeverity.ERROR);
319             assertTrue(e.getErrorTag() == ErrorTag.OPERATION_NOT_SUPPORTED);
320             assertTrue(e.getErrorType() == ErrorType.PROTOCOL);
321         }
322     }
323
324     private Document copyConfig(final String resource) throws Exception {
325         final CopyConfig copyConfig = new CopyConfig(SESSION_ID_FOR_REPORTING, getCurrentSchemaContext(),
326             getTransactionProvider());
327         return executeOperation(copyConfig, resource);
328     }
329
330     private Document copyConfig(final Document request) throws Exception {
331         final CopyConfig copyConfig = new CopyConfig(SESSION_ID_FOR_REPORTING, getCurrentSchemaContext(),
332             getTransactionProvider());
333         return executeOperation(copyConfig, request);
334     }
335 }