From: Moiz Raja Date: Wed, 23 Jul 2014 01:18:38 +0000 (+0000) Subject: Merge "Made config/mdsal/netconf features non-cyclic" X-Git-Tag: release/helium~455 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=7152d7675a13da768d03f11e3d1526f03de9781c;hp=fe5ef8066b0dd57df46e5b8806020ceb41716efb Merge "Made config/mdsal/netconf features non-cyclic" --- diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java index c89cfc1b9e..e2b6642501 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java @@ -867,6 +867,7 @@ public class FlowConfig extends ConfigurationObject implements Serializable { } continue; } + sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { if (!NetUtils.isIPAddressValid(sstr.group(1))) { @@ -875,7 +876,57 @@ public class FlowConfig extends ConfigurationObject implements Serializable { } continue; } - } + + sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + // If execution reached here, it means there is an Action + // which is not recognized by the controller. Return error + + return new Status(StatusCode.BADREQUEST, String.format("%s is an UnSupported Action", actiongrp)); + } } catch (NumberFormatException e) { return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage())); } diff --git a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java index 685ccdb7c4..3c367b9af4 100644 --- a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java +++ b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java @@ -760,9 +760,9 @@ public class frmTest { actions.add(ActionType.SET_NW_SRC.toString() + "=1.1.1.1"); actions.add(ActionType.SET_NW_DST.toString() + "=2.2.2.2"); actions.add(ActionType.CONTROLLER.toString()); - actions.add(ActionType.SET_NW_TOS.toString() + "1"); - actions.add(ActionType.SET_TP_SRC.toString() + "60"); - actions.add(ActionType.SET_TP_DST.toString() + "8080"); + actions.add(ActionType.SET_NW_TOS.toString() + "=1"); + actions.add(ActionType.SET_TP_SRC.toString() + "=60"); + actions.add(ActionType.SET_TP_DST.toString() + "=8080"); actions.add(ActionType.SET_NEXT_HOP.toString() + "=1.1.1.1"); return actions; diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java index eac65ad677..24ec89ebb2 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java @@ -4,7 +4,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChain; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -public interface BindingTransactionChain extends TransactionChain, DataObject> { +public interface BindingTransactionChain extends TransactionFactory, TransactionChain, DataObject> { @Override ReadOnlyTransaction newReadOnlyTransaction(); diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java index b60d8ff1be..ed43487df9 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java @@ -20,7 +20,8 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; *

* For more information on usage, please see the documentation in {@link AsyncDataBroker}. */ -public interface DataBroker extends AsyncDataBroker, DataObject, DataChangeListener>, BindingService, TransactionChainFactory, DataObject> { +public interface DataBroker extends TransactionFactory, AsyncDataBroker, DataObject, DataChangeListener>, BindingService, TransactionChainFactory, DataObject> { + @Override ReadOnlyTransaction newReadOnlyTransaction(); diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/TransactionFactory.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/TransactionFactory.java new file mode 100644 index 0000000000..4483cf9d66 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/TransactionFactory.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.api; + +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataTransactionFactory; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public interface TransactionFactory extends AsyncDataTransactionFactory, DataObject>{ + + @Override + ReadOnlyTransaction newReadOnlyTransaction(); + + @Override + ReadWriteTransaction newReadWriteTransaction(); + + @Override + WriteTransaction newWriteOnlyTransaction(); + +} diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java index 82903ea4ec..8964a80228 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java @@ -1,7 +1,15 @@ package org.opendaylight.controller.sal.connect.netconf.listener; -import java.util.Arrays; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + import java.util.Collection; +import java.util.HashSet; import java.util.Set; import org.opendaylight.controller.netconf.client.NetconfClientSession; @@ -10,24 +18,50 @@ import org.opendaylight.yangtools.yang.common.QName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - public final class NetconfSessionCapabilities { + private static final class ParameterMatcher { + private final Predicate predicate; + private final int skipLength; + + ParameterMatcher(final String name) { + predicate = new Predicate() { + @Override + public boolean apply(final String input) { + return input.startsWith(name); + } + }; - private static final Logger logger = LoggerFactory.getLogger(NetconfSessionCapabilities.class); + this.skipLength = name.length(); + } - private final Set capabilities; + private String from(final Iterable params) { + final Optional o = Iterables.tryFind(params, predicate); + if (!o.isPresent()) { + return null; + } + + return o.get().substring(skipLength); + } + } + + private static final Logger LOG = LoggerFactory.getLogger(NetconfSessionCapabilities.class); + private static final ParameterMatcher MODULE_PARAM = new ParameterMatcher("module="); + private static final ParameterMatcher REVISION_PARAM = new ParameterMatcher("revision="); + private static final ParameterMatcher BROKEN_REVISON_PARAM = new ParameterMatcher("amp;revision="); + private static final Splitter AMP_SPLITTER = Splitter.on('&'); + private static final Predicate CONTAINS_REVISION = new Predicate() { + @Override + public boolean apply(final String input) { + return input.contains("revision="); + } + }; private final Set moduleBasedCaps; + private final Set capabilities; private NetconfSessionCapabilities(final Set capabilities, final Set moduleBasedCaps) { - this.capabilities = capabilities; - this.moduleBasedCaps = moduleBasedCaps; + this.capabilities = Preconditions.checkNotNull(capabilities); + this.moduleBasedCaps = Preconditions.checkNotNull(moduleBasedCaps); } public Set getModuleBasedCaps() { @@ -65,47 +99,45 @@ public final class NetconfSessionCapabilities { } public static NetconfSessionCapabilities fromStrings(final Collection capabilities) { - final Set moduleBasedCaps = Sets.newHashSet(); + final Set moduleBasedCaps = new HashSet<>(); for (final String capability : capabilities) { - if(isModuleBasedCapability(capability)) { - final String[] parts = capability.split("\\?"); - final String namespace = parts[0]; - final FluentIterable queryParams = FluentIterable.from(Arrays.asList(parts[1].split("&"))); - - String revision = getStringAndTransform(queryParams, "revision=", "revision="); - - final String moduleName = getStringAndTransform(queryParams, "module=", "module="); + final int qmark = capability.indexOf('?'); + if (qmark == -1) { + continue; + } - if (revision == null) { - logger.debug("Netconf device was not reporting revision correctly, trying to get amp;revision="); - revision = getStringAndTransform(queryParams, "amp;revision=", "amp;revision="); + final String namespace = capability.substring(0, qmark); + final Iterable queryParams = AMP_SPLITTER.split(capability.substring(qmark + 1)); + final String moduleName = MODULE_PARAM.from(queryParams); + if (moduleName == null) { + continue; + } - if (revision == null) { - logger.warn("Netconf device returned revision incorrectly escaped for {}", capability); - } - } + String revision = REVISION_PARAM.from(queryParams); + if (revision != null) { moduleBasedCaps.add(QName.create(namespace, revision, moduleName)); + continue; } - } - - return new NetconfSessionCapabilities(Sets.newHashSet(capabilities), moduleBasedCaps); - } - private static boolean isModuleBasedCapability(final String capability) { - return capability.contains("?") && capability.contains("module=") && capability.contains("revision="); - } + /* + * We have seen devices which mis-escape revision, but the revision may not + * even be there. First check if there is a substring that matches revision. + */ + if (!Iterables.any(queryParams, CONTAINS_REVISION)) { + continue; + } - private static String getStringAndTransform(final Iterable queryParams, final String match, - final String substringToRemove) { - final Optional found = Iterables.tryFind(queryParams, new Predicate() { - @Override - public boolean apply(final String input) { - return input.startsWith(match); + LOG.debug("Netconf device was not reporting revision correctly, trying to get amp;revision="); + revision = BROKEN_REVISON_PARAM.from(queryParams); + if (revision == null) { + LOG.warn("Netconf device returned revision incorrectly escaped for {}, ignoring it", capability); } - }); - return found.isPresent() ? found.get().replaceAll(substringToRemove, "") : null; - } + // FIXME: do we really want to continue here? + moduleBasedCaps.add(QName.create(namespace, revision, moduleName)); + } + return new NetconfSessionCapabilities(ImmutableSet.copyOf(capabilities), ImmutableSet.copyOf(moduleBasedCaps)); + } } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java index 0aeec64690..3ec3eb1633 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java @@ -12,7 +12,6 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.net.URI; @@ -29,8 +28,8 @@ import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcError; -import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.Node; @@ -81,8 +80,7 @@ public class NetconfMessageTransformUtil { return null; } - for (final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : Lists - .reverse(identifier.getPath())) { + for (final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : identifier.getReversePathArguments()) { if (component instanceof InstanceIdentifier.NodeIdentifierWithPredicates) { previous = toNode((InstanceIdentifier.NodeIdentifierWithPredicates)component, previous); } else { @@ -142,12 +140,12 @@ public class NetconfMessageTransformUtil { ErrorSeverity severity = toRpcErrorSeverity( ex.getErrorSeverity() ); return severity == ErrorSeverity.ERROR ? - RpcResultBuilder.newError( + RpcResultBuilder.newError( toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(), ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() ) : - RpcResultBuilder.newWarning( - toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(), - ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() ); + RpcResultBuilder.newWarning( + toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(), + ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() ); } private static ErrorSeverity toRpcErrorSeverity( final NetconfDocumentedException.ErrorSeverity severity ) { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java index defaab629f..46ea4ff73c 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java @@ -102,11 +102,11 @@ public class NetconfDeviceTest { device.onRemoteSessionUp(sessionCaps, listener); verify(messageTransformer, timeout(10000).times(2)).toNotification(netconfMessage); - verify(facade, times(2)).onNotification(compositeNode); + verify(facade, timeout(10000).times(2)).onNotification(compositeNode); device.onNotification(netconfMessage); - verify(messageTransformer, times(3)).toNotification(netconfMessage); - verify(facade, times(3)).onNotification(compositeNode); + verify(messageTransformer, timeout(10000).times(3)).toNotification(netconfMessage); + verify(facade, timeout(10000).times(3)).onNotification(compositeNode); } @Test diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index bb7547d330..4e807b4e23 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -490,7 +490,13 @@ public class RestconfImpl implements RestconfService { } final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded); - RpcDefinition rpc = controllerContext.getRpcDefinition(identifierDecoded); + + RpcDefinition rpc = null; + if (mountPoint == null) { + rpc = controllerContext.getRpcDefinition(identifierDecoded); + } else { + rpc = findRpc(mountPoint.getSchemaContext(), identifierDecoded); + } if (rpc == null) { throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT); @@ -504,6 +510,25 @@ public class RestconfImpl implements RestconfService { } + private RpcDefinition findRpc(final SchemaContext schemaContext, final String identifierDecoded) { + final String[] splittedIdentifier = identifierDecoded.split(":"); + if (splittedIdentifier.length != 2) { + throw new RestconfDocumentedException(identifierDecoded + + " couldn't be splitted to 2 parts (module:rpc name)", ErrorType.APPLICATION, + ErrorTag.INVALID_VALUE); + } + for (Module module : schemaContext.getModules()) { + if (module.getName().equals(splittedIdentifier[0])) { + for (RpcDefinition rpcDefinition : module.getRpcs()) { + if (rpcDefinition.getQName().getLocalName().equals(splittedIdentifier[1])) { + return rpcDefinition; + } + } + } + } + return null; + } + private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload, boolean prettyPrint) { if (rpcExecutor == null) { throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java index 313b766ed3..2adf9b5530 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -36,7 +36,6 @@ import javax.ws.rs.core.UriInfo; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; - import org.opendaylight.controller.sal.core.api.mount.MountInstance; import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; import org.opendaylight.controller.sal.restconf.impl.ControllerContext; @@ -298,6 +297,14 @@ public class InvokeRpcMethodTest { assertNotNull(output.getSchema()); } + /** + * + * Tests calling of RestConfImpl method invokeRpc. In the method there is searched rpc in remote schema context. + * This rpc is then executed. + * + * I wasn't able to simulate calling of rpc on remote device therefore this testing method raise method when rpc is + * invoked. + */ @Test public void testMountedRpcCallNoPayload_Success() throws Exception { RpcResult rpcResult = RpcResultBuilder.success().build(); @@ -313,21 +320,32 @@ public class InvokeRpcMethodTest { MountInstance mockMountPoint = mock(MountInstance.class); when(mockMountPoint.rpc(eq(cancelToastQName), any(CompositeNode.class))).thenReturn(mockListener); + when(mockMountPoint.getSchemaContext()).thenReturn(TestUtils.loadSchemaContext("/invoke-rpc")); + InstanceIdWithSchemaNode mockedInstanceId = mock(InstanceIdWithSchemaNode.class); when(mockedInstanceId.getMountPoint()).thenReturn(mockMountPoint); ControllerContext mockedContext = mock(ControllerContext.class); - String cancelToastStr = "toaster:cancel-toast"; - when(mockedContext.urlPathArgDecode(cancelToastStr)).thenReturn(cancelToastStr); - when(mockedContext.getRpcDefinition(cancelToastStr)).thenReturn(mockRpc); + String rpcNoop = "invoke-rpc-module:rpc-noop"; + when(mockedContext.urlPathArgDecode(rpcNoop)).thenReturn(rpcNoop); + when(mockedContext.getRpcDefinition(rpcNoop)).thenReturn(mockRpc); when( - mockedContext.toMountPointIdentifier("opendaylight-inventory:nodes/node/" - + "REMOTE_HOST/yang-ext:mount/toaster:cancel-toast")).thenReturn(mockedInstanceId); + mockedContext.toMountPointIdentifier(eq("opendaylight-inventory:nodes/node/" + + "REMOTE_HOST/yang-ext:mount/invoke-rpc-module:rpc-noop"))).thenReturn(mockedInstanceId); restconfImpl.setControllerContext(mockedContext); - StructuredData output = restconfImpl.invokeRpc( - "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast", "", uriInfo); - assertEquals(null, output); + try { + restconfImpl.invokeRpc( + "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/invoke-rpc-module:rpc-noop", "", + uriInfo); + fail("RestconfDocumentedException wasn't raised"); + } catch (RestconfDocumentedException e) { + List errors = e.getErrors(); + assertNotNull(errors); + assertEquals(1, errors.size()); + assertEquals(ErrorType.APPLICATION, errors.iterator().next().getErrorType()); + assertEquals(ErrorTag.OPERATION_FAILED, errors.iterator().next().getErrorTag()); + } // additional validation in the fact that the restconfImpl does not // throw an exception. diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang index ba06645354..208c2164d5 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang @@ -16,5 +16,8 @@ module invoke-rpc-module { } } } - + + rpc rpc-noop { + } + } \ No newline at end of file