summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/WriteTransaction.java4
-rw-r--r--infra/it/it-test/pom.xml22
-rw-r--r--infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/TestValidate.java175
-rw-r--r--infra/it/it-test/src/test/resources/messages/commit.xml19
-rw-r--r--infra/it/it-test/src/test/resources/messages/edit-config/edit-config-missing-mandatory-node.xml35
-rw-r--r--infra/it/it-test/src/test/resources/messages/rpc-reply_ok.xml19
-rw-r--r--infra/it/it-test/src/test/resources/models/test-validate.yang27
7 files changed, 298 insertions, 3 deletions
diff --git a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/WriteTransaction.java b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/WriteTransaction.java
index 648d435..8e7dca0 100644
--- a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/WriteTransaction.java
+++ b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/WriteTransaction.java
@@ -29,7 +29,6 @@ import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.fd.honeycomb.data.DataModification;
-import io.fd.honeycomb.translate.TranslationException;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -41,7 +40,6 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -143,7 +141,7 @@ final class WriteTransaction implements DOMDataWriteTransaction {
}
status = COMMITED;
- } catch (DataValidationFailedException | TranslationException e) {
+ } catch (Exception e) {
status = FAILED;
LOG.error("Submit failed", e);
return Futures.immediateFailedCheckedFuture(
diff --git a/infra/it/it-test/pom.xml b/infra/it/it-test/pom.xml
index 41d48ca..25bb575 100644
--- a/infra/it/it-test/pom.xml
+++ b/infra/it/it-test/pom.xml
@@ -69,6 +69,28 @@
<artifactId>honeycomb-test-model</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <version>1.6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-test-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>mdsal-netconf-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/TestValidate.java b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/TestValidate.java
new file mode 100644
index 0000000..5bc933f
--- /dev/null
+++ b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/TestValidate.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.data.impl;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration.DEFAULT_CONFIGURATION;
+
+import com.google.common.io.ByteSource;
+import com.google.common.util.concurrent.Futures;
+import io.fd.honeycomb.data.ReadableDataManager;
+import java.io.StringWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.custommonkey.xmlunit.DetailedDiff;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.util.xml.DocumentedException;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.netconf.mdsal.connector.ops.Commit;
+import org.opendaylight.netconf.mdsal.connector.ops.EditConfig;
+import org.opendaylight.netconf.util.test.NetconfXmlUnitRecursiveQualifier;
+import org.opendaylight.netconf.util.test.XmlFileLoader;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+public class TestValidate {
+ private static final Logger LOG = LoggerFactory.getLogger(TestValidate.class);
+ private static final String SESSION_ID_FOR_REPORTING = "netconf-test-session";
+ private static final Document RPC_REPLY_OK = getReplyOk();
+
+ @Mock
+ private ReadableDataManager operationalData;
+ @Mock
+ private SchemaService schemaService;
+
+ private CurrentSchemaContext currentSchemaContext;
+ private DataBroker dataBroker;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ final SchemaContext schemaContext =
+ YangParserTestUtils.parseYangResources(TestValidate.class, "/models/test-validate.yang");
+ when(schemaService.registerSchemaContextListener(any())).thenAnswer(invocation -> {
+ SchemaContextListener listener = invocation.getArgument(0);
+ listener.onGlobalContextUpdated(schemaContext);
+ return new ListenerRegistration<SchemaContextListener>() {
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public SchemaContextListener getInstance() {
+ return listener;
+ }
+ };
+ });
+ currentSchemaContext = new CurrentSchemaContext(schemaService, sourceIdentifier -> {
+ final YangTextSchemaSource yangTextSchemaSource =
+ YangTextSchemaSource.delegateForByteSource(sourceIdentifier, ByteSource.wrap("module test".getBytes()));
+ return Futures.immediateCheckedFuture(yangTextSchemaSource);
+ });
+
+ final DataTree dataTree = new InMemoryDataTreeFactory().create(DEFAULT_CONFIGURATION);
+ dataTree.setSchemaContext(schemaContext);
+ dataBroker = DataBroker.create(new ModifiableDataTreeManager(dataTree), operationalData);
+ XMLUnit.setIgnoreWhitespace(true);
+ XMLUnit.setIgnoreAttributeOrder(true);
+ }
+
+ @Test
+ public void testValidateMissingMandatoryNode() throws Exception {
+ final TransactionProvider transactionProvider = new TransactionProvider(dataBroker, SESSION_ID_FOR_REPORTING);
+ verifyResponse(edit("messages/edit-config/edit-config-missing-mandatory-node.xml", transactionProvider));
+ try {
+ verifyResponse(commit(transactionProvider));
+ fail("Should have failed due to missing mandatory node");
+ } catch (DocumentedException e) {
+ assertTrue(e.getMessage().contains("missing mandatory descendant"));
+ }
+ }
+
+ private static Document getReplyOk() {
+ Document doc;
+ try {
+ doc = XmlFileLoader.xmlFileToDocument("messages/rpc-reply_ok.xml");
+ } catch (final Exception e) {
+ LOG.debug("unable to load rpc reply ok.", e);
+ doc = XmlUtil.newDocument();
+ }
+ return doc;
+ }
+
+ private static void verifyResponse(final Document actual) throws Exception {
+ final DetailedDiff dd = new DetailedDiff(new Diff(RPC_REPLY_OK, actual));
+ dd.overrideElementQualifier(new NetconfXmlUnitRecursiveQualifier());
+ if (!dd.similar()) {
+ LOG.warn("Actual response:");
+ printDocument(actual);
+ LOG.warn("Expected response:");
+ printDocument(RPC_REPLY_OK);
+ fail("Differences found: " + dd.toString());
+ }
+ }
+
+ private static void printDocument(final Document doc) throws Exception {
+ final TransformerFactory tf = TransformerFactory.newInstance();
+ final Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+ final StringWriter writer = new StringWriter();
+ transformer.transform(new DOMSource(doc), new StreamResult(writer));
+ LOG.warn(writer.getBuffer().toString());
+ }
+
+ private Document edit(final String resource, final TransactionProvider transactionProvider) throws Exception {
+ final EditConfig editConfig = new EditConfig(SESSION_ID_FOR_REPORTING, currentSchemaContext,
+ transactionProvider);
+ return executeOperation(editConfig, resource);
+ }
+
+ private static Document commit(final TransactionProvider transactionProvider) throws Exception {
+ final Commit commit = new Commit(SESSION_ID_FOR_REPORTING, transactionProvider);
+ return executeOperation(commit, "messages/commit.xml");
+ }
+
+ private static Document executeOperation(final NetconfOperation op, final String filename) throws Exception {
+ final Document request = XmlFileLoader.xmlFileToDocument(filename);
+ final Document response = op.handle(request, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+ LOG.debug("Got response {}", response);
+ return response;
+ }
+}
diff --git a/infra/it/it-test/src/test/resources/messages/commit.xml b/infra/it/it-test/src/test/resources/messages/commit.xml
new file mode 100644
index 0000000..a4a98f4
--- /dev/null
+++ b/infra/it/it-test/src/test/resources/messages/commit.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (c) 2018 Cisco and/or its affiliates.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at:
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rpc message-id="a" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <commit/>
+</rpc>
diff --git a/infra/it/it-test/src/test/resources/messages/edit-config/edit-config-missing-mandatory-node.xml b/infra/it/it-test/src/test/resources/messages/edit-config/edit-config-missing-mandatory-node.xml
new file mode 100644
index 0000000..829ef56
--- /dev/null
+++ b/infra/it/it-test/src/test/resources/messages/edit-config/edit-config-missing-mandatory-node.xml
@@ -0,0 +1,35 @@
+<!--
+ ~ Copyright (c) 2018 Cisco and/or its affiliates.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at:
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rpc message-id="a" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>none</default-operation>
+ <config>
+ <top-container xmlns="urn:honeycomb:params:xml:ns:yang:test:validate" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="create">
+ <list-in-container>
+ <name>item1</name>>
+ </list-in-container>
+ <list-in-container>
+ <name>item2</name>
+ <description>description2</description>
+ </list-in-container>
+ </top-container>
+ </config>
+ </edit-config>
+</rpc> \ No newline at end of file
diff --git a/infra/it/it-test/src/test/resources/messages/rpc-reply_ok.xml b/infra/it/it-test/src/test/resources/messages/rpc-reply_ok.xml
new file mode 100644
index 0000000..df205b6
--- /dev/null
+++ b/infra/it/it-test/src/test/resources/messages/rpc-reply_ok.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (c) 2018 Cisco and/or its affiliates.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at:
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="a">
+ <ok/>
+</rpc-reply> \ No newline at end of file
diff --git a/infra/it/it-test/src/test/resources/models/test-validate.yang b/infra/it/it-test/src/test/resources/models/test-validate.yang
new file mode 100644
index 0000000..1440456
--- /dev/null
+++ b/infra/it/it-test/src/test/resources/models/test-validate.yang
@@ -0,0 +1,27 @@
+module test-validate {
+ yang-version 1;
+ namespace "urn:honeycomb:params:xml:ns:yang:test:validate";
+ prefix "td";
+
+ revision "2018-06-08" {
+ description "Initial revision";
+ }
+
+ container top-container {
+ leaf name {
+ type string;
+ }
+ list list-in-container {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ leaf description {
+ type string;
+ mandatory true;
+ }
+ }
+ }
+}