2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.netconf.mdsal.connector.ops;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
16 import com.google.common.io.ByteSource;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.StringWriter;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.EnumMap;
25 import java.util.List;
26 import java.util.concurrent.ExecutorService;
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.transform.OutputKeys;
29 import javax.xml.transform.Transformer;
30 import javax.xml.transform.TransformerException;
31 import javax.xml.transform.TransformerFactory;
32 import javax.xml.transform.dom.DOMSource;
33 import javax.xml.transform.stream.StreamResult;
34 import org.custommonkey.xmlunit.DetailedDiff;
35 import org.custommonkey.xmlunit.Diff;
36 import org.custommonkey.xmlunit.XMLUnit;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.opendaylight.controller.cluster.datastore.ConcurrentDOMDataBroker;
40 import org.opendaylight.controller.config.util.xml.DocumentedException;
41 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorSeverity;
42 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorTag;
43 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorType;
44 import org.opendaylight.controller.config.util.xml.XmlElement;
45 import org.opendaylight.controller.config.util.xml.XmlUtil;
46 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
47 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
48 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
49 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
50 import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
51 import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
52 import org.opendaylight.controller.netconf.mdsal.connector.ops.get.Get;
53 import org.opendaylight.controller.netconf.mdsal.connector.ops.get.GetConfig;
54 import org.opendaylight.controller.netconf.util.test.NetconfXmlUnitRecursiveQualifier;
55 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
56 import org.opendaylight.controller.sal.core.api.model.SchemaService;
57 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
58 import org.opendaylight.yangtools.concepts.ListenerRegistration;
59 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
60 import org.opendaylight.yangtools.yang.common.QName;
61 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
62 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
63 import org.opendaylight.yangtools.yang.model.api.Module;
64 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
65 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
66 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
67 import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
68 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71 import org.w3c.dom.Document;
72 import org.w3c.dom.Node;
73 import org.w3c.dom.NodeList;
74 import org.xml.sax.SAXException;
76 public class NetconfMDSalMappingTest {
78 private static final Logger LOG = LoggerFactory.getLogger(NetconfMDSalMappingTest.class);
80 private static final String RPC_REPLY_ELEMENT = "rpc-reply";
81 private static final String DATA_ELEMENT = "data";
82 private static final String FILTER_NODE = "filter";
83 private static final String GET_CONFIG = "get-config";
84 private static final QName TOP = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "top");
85 private static final QName USERS = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "users");
86 private static final QName USER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "user");
87 private static final QName MODULES = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "modules");
88 private static final QName AUGMENTED_CONTAINER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "augmented-container");
89 private static final QName AUGMENTED_STRING_IN_CONT = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "identifier");
90 private static final QName CHOICE_NODE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "choice-node");
91 private static final QName AUGMENTED_CASE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "augmented-case");
92 private static final QName CHOICE_WRAPPER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "choice-wrapper");
93 private static final QName INNER_CHOICE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "inner-choice");
94 private static final QName INNER_CHOICE_TEXT = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "text");
96 private static final YangInstanceIdentifier AUGMENTED_CONTAINER_IN_MODULES =
97 YangInstanceIdentifier.builder().node(TOP).node(MODULES).build().node(new AugmentationIdentifier(Collections.singleton(AUGMENTED_CONTAINER)));
99 private static Document RPC_REPLY_OK = null;
103 RPC_REPLY_OK = XmlFileLoader.xmlFileToDocument("messages/mapping/rpc-reply_ok.xml");
104 } catch (Exception e) {
105 LOG.debug("unable to load rpc reply ok.", e);
106 RPC_REPLY_OK = XmlUtil.newDocument();
110 private CurrentSchemaContext currentSchemaContext = null;
111 private SchemaContext schemaContext = null;
112 private String sessionIdForReporting = "netconf-test-session1";
114 private TransactionProvider transactionProvider = null;
117 public void setUp() throws Exception {
119 XMLUnit.setIgnoreWhitespace(true);
120 XMLUnit.setIgnoreAttributeOrder(true);
122 this.schemaContext = parseSchemas(getYangSchemas());
123 schemaContext.getModules();
124 final SchemaService schemaService = createSchemaService();
126 final DOMStore operStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", schemaService);
127 final DOMStore configStore = InMemoryDOMDataStoreFactory.create("DOM-CFG", schemaService);
129 final EnumMap<LogicalDatastoreType, DOMStore> datastores = new EnumMap<>(LogicalDatastoreType.class);
130 datastores.put(LogicalDatastoreType.CONFIGURATION, configStore);
131 datastores.put(LogicalDatastoreType.OPERATIONAL, operStore);
133 ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
134 16, 16, "CommitFutures");
136 final ConcurrentDOMDataBroker cdb = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
137 this.transactionProvider = new TransactionProvider(cdb, sessionIdForReporting);
138 this.currentSchemaContext = new CurrentSchemaContext(schemaService);
143 public void testEmptyDatastore() throws Exception {
144 assertEmptyDatastore(get());
145 assertEmptyDatastore(getConfigCandidate());
146 assertEmptyDatastore(getConfigRunning());
150 public void testDiscard() throws Exception {
154 fail("Should have failed, need to execute an edit before discard");
155 } catch (DocumentedException e) {
156 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
157 assertTrue(e.getErrorTag() == ErrorTag.operation_failed);
158 assertTrue(e.getErrorType() == ErrorType.application);
163 public void testIncorrectGet() throws Exception {
166 executeOperation(new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider), "messages/mapping/bad_getConfig.xml");
167 fail("Should have failed, this is an incorrect request");
168 } catch (DocumentedException e) {
169 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
170 assertTrue(e.getErrorTag() == ErrorTag.operation_failed);
171 assertTrue(e.getErrorType() == ErrorType.application);
175 executeOperation(new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider), "messages/mapping/bad_namespace_getConfig.xml");
176 fail("Should have failed, this is an incorrect request");
177 } catch (DocumentedException e) {
178 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
179 assertTrue(e.getErrorTag() == ErrorTag.operation_failed);
180 assertTrue(e.getErrorType() == ErrorType.application);
187 public void testEditRunning() throws Exception {
190 edit("messages/mapping/editConfigs/editConfig_running.xml");
191 fail("Should have failed - edit config on running datastore is not supported");
192 } catch (DocumentedException e) {
193 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
194 assertTrue(e.getErrorTag() == ErrorTag.operation_not_supported);
195 assertTrue(e.getErrorType() == ErrorType.protocol);
201 public void testCandidateTransaction() throws Exception {
203 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n1.xml"), RPC_REPLY_OK);
204 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
205 assertEmptyDatastore(getConfigRunning());
207 verifyResponse(discardChanges(), RPC_REPLY_OK);
208 assertEmptyDatastore(getConfigCandidate());
213 public void testEditWithCommit() throws Exception {
215 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n1.xml"), RPC_REPLY_OK);
216 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
218 verifyResponse(commit(), RPC_REPLY_OK);
219 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
226 public void testMultipleEditsWithMerge() throws Exception {
228 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
229 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_1.xml"));
230 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
231 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_2.xml"));
232 assertEmptyDatastore(getConfigRunning());
234 verifyResponse(commit(), RPC_REPLY_OK);
235 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_2.xml"));
242 public void testMoreComplexEditConfigs() throws Exception {
244 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
245 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
247 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_2.xml"), RPC_REPLY_OK);
248 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_more_complex_merge.xml"));
250 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_3.xml"), RPC_REPLY_OK);
251 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_more_complex_merge_2.xml"));
253 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_4_replace.xml"), RPC_REPLY_OK);
254 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_replace.xml"));
255 verifyResponse(commit(), RPC_REPLY_OK);
257 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_replace.xml"));
259 verifyResponse(edit("messages/mapping/editConfigs/editConfig_replace_default.xml"), RPC_REPLY_OK);
260 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_replace_default_control.xml"));
261 verifyResponse(commit(), RPC_REPLY_OK);
263 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_replace_default_control.xml"));
270 public void testLock() throws Exception {
272 verifyResponse(lockCandidate(), RPC_REPLY_OK);
276 fail("Should have failed - locking of running datastore is not supported");
277 } catch (DocumentedException e) {
278 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
279 assertTrue(e.getErrorTag() == ErrorTag.operation_not_supported);
280 assertTrue(e.getErrorType() == ErrorType.application);
286 fail("Should have failed, target is missing");
287 } catch (DocumentedException e) {
288 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
289 assertTrue(e.getErrorTag() == ErrorTag.invalid_value);
290 assertTrue(e.getErrorType() == ErrorType.application);
295 public void testUnlock() throws Exception {
297 verifyResponse(unlockCandidate(), RPC_REPLY_OK);
301 fail("Should have failed - unlocking of running datastore is not supported");
302 } catch (DocumentedException e) {
303 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
304 assertTrue(e.getErrorTag() == ErrorTag.operation_not_supported);
305 assertTrue(e.getErrorType() == ErrorType.application);
309 unlockWithoutTarget();
310 fail("Should have failed, target is missing");
311 } catch (DocumentedException e) {
312 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
313 assertTrue(e.getErrorTag() == ErrorTag.invalid_value);
314 assertTrue(e.getErrorType() == ErrorType.application);
319 public void testEditWithCreate() throws Exception {
321 verifyResponse(edit("messages/mapping/editConfigs/editConfig_create.xml"), RPC_REPLY_OK);
322 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_create_n1_control.xml"));
326 edit("messages/mapping/editConfigs/editConfig_create.xml");
327 fail("Create should have failed - data already exists");
328 } catch (DocumentedException e) {
329 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
330 assertTrue(e.getErrorTag() == ErrorTag.data_exists);
331 assertTrue(e.getErrorType() == ErrorType.protocol);
334 verifyResponse(discardChanges(), RPC_REPLY_OK);
339 public void testDeleteNonExisting() throws Exception {
341 assertEmptyDatastore(getConfigCandidate());
342 assertEmptyDatastore(getConfigRunning());
345 edit("messages/mapping/editConfigs/editConfig_delete-top.xml");
346 fail("Delete should have failed - data is missing");
347 } catch (DocumentedException e) {
348 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
349 assertTrue(e.getErrorTag() == ErrorTag.data_missing);
350 assertTrue(e.getErrorType() == ErrorType.protocol);
356 public void testEditMissingDefaultOperation() throws Exception {
358 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_1.xml"), RPC_REPLY_OK);
359 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_2.xml"), RPC_REPLY_OK);
360 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_control.xml"));
362 verifyResponse(commit(), RPC_REPLY_OK);
363 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_control.xml"));
368 public static void printDocument(Document doc) throws IOException, TransformerException {
369 TransformerFactory tf = TransformerFactory.newInstance();
370 Transformer transformer = tf.newTransformer();
371 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
372 transformer.setOutputProperty(OutputKeys.METHOD, "xml");
373 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
374 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
375 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
377 StringWriter writer = new StringWriter();
378 transformer.transform(new DOMSource(doc),
379 new StreamResult(writer));
380 LOG.warn(writer.getBuffer().toString());
384 public void testEditConfigWithMultipleOperations() throws Exception {
387 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_setup.xml"), RPC_REPLY_OK);
388 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_1.xml"), RPC_REPLY_OK);
390 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_2.xml"), RPC_REPLY_OK);
391 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_2_control.xml"));
393 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_3_leaf_operations.xml"), RPC_REPLY_OK);
394 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_3_control.xml"));
398 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_setup.xml"), RPC_REPLY_OK);
399 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_default-replace.xml"), RPC_REPLY_OK);
402 edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_create_existing.xml");
404 } catch (DocumentedException e) {
405 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
406 assertTrue(e.getErrorTag() == ErrorTag.data_exists);
407 assertTrue(e.getErrorType() == ErrorType.protocol);
410 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_delete_children_operations.xml"), RPC_REPLY_OK);
411 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_delete_children_operations_control.xml"));
412 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_remove-non-existing.xml"), RPC_REPLY_OK);
415 edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_delete-non-existing.xml");
417 } catch (DocumentedException e) {
418 assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
419 assertTrue(e.getErrorTag() == ErrorTag.data_missing);
420 assertTrue(e.getErrorType() == ErrorType.protocol);
423 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_5_choice_setup.xml"), RPC_REPLY_OK);
424 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_5_choice_setup-control.xml"));
426 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_5_choice_setup2.xml"), RPC_REPLY_OK);
427 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_5_choice_setup2-control.xml"));
429 verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_operations_5_choice_delete.xml"), RPC_REPLY_OK);
430 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_operations_4_delete_children_operations_control.xml"));
436 public void testFiltering() throws Exception {
438 assertEmptyDatastore(getConfigCandidate());
439 assertEmptyDatastore(getConfigRunning());
441 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-config-empty-filter.xml"),
442 XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
443 verifyResponse(getWithFilter("messages/mapping/filters/get-empty-filter.xml"),
444 XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
446 verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
447 verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
448 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-users.xml"),
449 XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
451 verifyResponse(edit("messages/mapping/editConfigs/editConfig-filtering-setup.xml"), RPC_REPLY_OK);
452 verifyResponse(commit(), RPC_REPLY_OK);
454 //TODO uncomment these tests once we can parse KeyedListNode as a selection node, currently you cannot use a KeyedList as a selection node in filter
455 // verifyFilterIdentifier("messages/mapping/filters/get-filter-alluser.xml",
456 // YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
457 verifyFilterIdentifier("messages/mapping/filters/get-filter-company-info.xml",
458 YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
459 verifyFilterIdentifier("messages/mapping/filters/get-filter-modules-and-admin.xml",
460 YangInstanceIdentifier.builder().node(TOP).build());
461 verifyFilterIdentifier("messages/mapping/filters/get-filter-only-names-types.xml",
462 YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
463 // verifyFilterIdentifier("messages/mapping/filters/get-filter-specific-module-type-and-user.xml",
464 // YangInstanceIdentifier.builder().node(TOP).build());
465 // verifyFilterIdentifier("messages/mapping/filters/get-filter-superuser.xml",
466 // YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
467 verifyFilterIdentifier("messages/mapping/filters/get-filter-users.xml",
468 YangInstanceIdentifier.builder().node(TOP).node(USERS).build());
470 YangInstanceIdentifier ident = YangInstanceIdentifier.
471 builder(AUGMENTED_CONTAINER_IN_MODULES).
472 node(AUGMENTED_CONTAINER).
473 node(AUGMENTED_STRING_IN_CONT).build();
475 verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-string.xml", ident);
476 verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case.xml",
477 YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(AUGMENTED_CASE).build());
479 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case.xml"),
480 XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case.xml"));
481 verifyResponse(edit("messages/mapping/editConfigs/editConfig-filtering-setup2.xml"), RPC_REPLY_OK);
482 verifyResponse(commit(), RPC_REPLY_OK);
484 verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case-inner-choice.xml",
485 YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(CHOICE_WRAPPER).build());
486 verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case-inner-case.xml",
487 YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(CHOICE_WRAPPER).node(INNER_CHOICE).node(INNER_CHOICE_TEXT).build());
489 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-string.xml"),
490 XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-string.xml"));
491 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case-inner-choice.xml"),
492 XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case-inner-choice.xml"));
493 verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case-inner-case.xml"),
494 XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case-inner-choice.xml"));
496 verifyResponse(edit("messages/mapping/editConfigs/editConfig_delete-top.xml"), RPC_REPLY_OK);
497 verifyResponse(commit(), RPC_REPLY_OK);
501 private void verifyFilterIdentifier(String resource, YangInstanceIdentifier identifier) throws Exception{
502 TestingGetConfig getConfig = new TestingGetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
503 Document request = XmlFileLoader.xmlFileToDocument(resource);
504 YangInstanceIdentifier iid = getConfig.getInstanceIdentifierFromDocument(request);
505 assertTrue(iid.equals(identifier));
508 private class TestingGetConfig extends GetConfig{
509 public TestingGetConfig(String sessionId, CurrentSchemaContext schemaContext, TransactionProvider transactionProvider) {
510 super(sessionId, schemaContext, transactionProvider);
513 public YangInstanceIdentifier getInstanceIdentifierFromDocument(Document request) throws DocumentedException {
514 XmlElement filterElement = XmlElement.fromDomDocument(request).getOnlyChildElement(GET_CONFIG).getOnlyChildElement(FILTER_NODE);
515 return getInstanceIdentifierFromFilter(filterElement);
519 private void deleteDatastore() throws Exception{
520 verifyResponse(edit("messages/mapping/editConfigs/editConfig_delete-root.xml"), RPC_REPLY_OK);
521 assertEmptyDatastore(getConfigCandidate());
523 verifyResponse(commit(), RPC_REPLY_OK);
524 assertEmptyDatastore(getConfigRunning());
527 private void verifyResponse(Document response, Document template) throws IOException, TransformerException {
528 DetailedDiff dd = new DetailedDiff(new Diff(response, template));
529 dd.overrideElementQualifier(new NetconfXmlUnitRecursiveQualifier());
531 printDocument(response);
532 printDocument(template);
534 assertTrue(dd.toString(), dd.similar());
537 private void assertEmptyDatastore(Document response) {
539 NodeList nodes = response.getChildNodes();
540 assertTrue(nodes.getLength() == 1);
542 assertEquals(nodes.item(0).getLocalName(), RPC_REPLY_ELEMENT);
544 NodeList replyNodes = nodes.item(0).getChildNodes();
545 assertTrue(replyNodes.getLength() == 1);
547 Node dataNode = replyNodes.item(0);
548 assertEquals(dataNode.getLocalName(), DATA_ELEMENT);
549 assertFalse(dataNode.hasChildNodes());
553 private Document commit() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
554 Commit commit = new Commit(sessionIdForReporting, transactionProvider);
555 return executeOperation(commit, "messages/mapping/commit.xml");
558 private Document discardChanges() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
559 DiscardChanges discardOp = new DiscardChanges(sessionIdForReporting, transactionProvider);
560 return executeOperation(discardOp, "messages/mapping/discardChanges.xml");
563 private Document edit(String resource) throws DocumentedException, ParserConfigurationException, SAXException, IOException {
564 EditConfig editConfig = new EditConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
565 return executeOperation(editConfig, resource);
568 private Document get() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
569 Get get = new Get(sessionIdForReporting, currentSchemaContext, transactionProvider);
570 return executeOperation(get, "messages/mapping/get.xml");
573 private Document getWithFilter(String resource) throws DocumentedException, ParserConfigurationException, SAXException, IOException {
574 Get get = new Get(sessionIdForReporting, currentSchemaContext, transactionProvider);
575 return executeOperation(get, resource);
578 private Document getConfigRunning() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
579 GetConfig getConfig = new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
580 return executeOperation(getConfig, "messages/mapping/getConfig.xml");
583 private Document getConfigCandidate() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
584 GetConfig getConfig = new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
585 return executeOperation(getConfig, "messages/mapping/getConfig_candidate.xml");
588 private Document getConfigWithFilter(String resource) throws DocumentedException, ParserConfigurationException, SAXException, IOException {
589 GetConfig getConfig = new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
590 return executeOperation(getConfig, resource);
593 private Document lock() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
594 Lock lock = new Lock(sessionIdForReporting);
595 return executeOperation(lock, "messages/mapping/lock.xml");
598 private Document unlock() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
599 Unlock unlock = new Unlock(sessionIdForReporting);
600 return executeOperation(unlock, "messages/mapping/unlock.xml");
603 private Document lockWithoutTarget() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
604 Lock lock = new Lock(sessionIdForReporting);
605 return executeOperation(lock, "messages/mapping/lock_notarget.xml");
608 private Document unlockWithoutTarget() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
609 Unlock unlock = new Unlock(sessionIdForReporting);
610 return executeOperation(unlock, "messages/mapping/unlock_notarget.xml");
613 private Document lockCandidate() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
614 Lock lock = new Lock(sessionIdForReporting);
615 return executeOperation(lock, "messages/mapping/lock_candidate.xml");
618 private Document unlockCandidate() throws DocumentedException, ParserConfigurationException, SAXException, IOException {
619 Unlock unlock = new Unlock(sessionIdForReporting);
620 return executeOperation(unlock, "messages/mapping/unlock_candidate.xml");
623 private Document executeOperation(NetconfOperation op, String filename) throws ParserConfigurationException, SAXException, IOException, DocumentedException {
624 final Document request = XmlFileLoader.xmlFileToDocument(filename);
625 final Document response = op.handle(request, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
627 LOG.debug("Got response {}" , response);
631 private Collection<InputStream> getYangSchemas() {
632 final List<String> schemaPaths = Arrays.asList("/META-INF/yang/config.yang", "/yang/mdsal-netconf-mapping-test.yang");
633 final List<InputStream> schemas = new ArrayList<>();
635 for (String schemaPath : schemaPaths) {
636 InputStream resourceAsStream = getClass().getResourceAsStream(schemaPath);
637 schemas.add(resourceAsStream);
643 private SchemaContext parseSchemas(Collection<InputStream> schemas) throws IOException, YangSyntaxErrorException {
644 final YangParserImpl parser = new YangParserImpl();
645 Collection<ByteSource> sources = BuilderUtils.streamsToByteSources(schemas);
646 return parser.parseSources(sources);
649 private SchemaService createSchemaService() {
650 return new SchemaService() {
653 public void addModule(Module module) {
657 public void removeModule(Module module) {
662 public SchemaContext getSessionContext() {
663 return schemaContext;
667 public SchemaContext getGlobalContext() {
668 return schemaContext;
672 public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) {
673 listener.onGlobalContextUpdated(getGlobalContext());
674 return new ListenerRegistration<SchemaContextListener>() {
676 public void close() {
681 public SchemaContextListener getInstance() {