import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
+import java.util.function.Function;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.Encoded;
import javax.ws.rs.GET;
-import javax.ws.rs.NotFoundException;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
-import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.restconf.api.MediaTypes;
import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.restconf.common.errors.RestconfFuture;
/**
* List RPC and action operations in RFC7951 format.
*
- * @return A string containing a JSON document conforming to both RFC8040 and RFC7951.
+ * @param ar {@link AsyncResponse} which needs to be completed
*/
@GET
@Path("/operations")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
- public String operationsJsonGET() {
- return server.operationsGET().toJSON();
+ public void operationsJsonGET(@Suspended final AsyncResponse ar) {
+ completeOperationsJsonGet(server.operationsGET(), ar);
}
/**
* Retrieve list of operations and actions supported by the server or device in JSON format.
*
* @param operation path parameter to identify device and/or operation
- * @return A string containing a JSON document conforming to both RFC8040 and RFC7951.
+ * @param ar {@link AsyncResponse} which needs to be completed
*/
@GET
@Path("/operations/{operation:.+}")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
- public String operationsJsonGET(@PathParam("operation") final String operation) {
- return operationsGET(operation).toJSON();
+ public void operationsJsonGET(@PathParam("operation") final String operation, final AsyncResponse ar) {
+ completeOperationsGet(server.operationsGET(operation), ar, OperationsGetResult::toJSON);
+ }
+
+ private static void completeOperationsJsonGet(final RestconfFuture<OperationsGetResult> future,
+ final AsyncResponse ar) {
+ completeOperationsGet(future, ar, OperationsGetResult::toJSON);
}
/**
* List RPC and action operations in RFC8040 XML format.
*
- * @return A string containing an XML document conforming to both RFC8040 section 11.3.1 and page 84.
+ * @param ar {@link AsyncResponse} which needs to be completed
*/
@GET
@Path("/operations")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
- public String operationsXmlGET() {
- return server.operationsGET().toXML();
+ public void operationsXmlGET(@Suspended final AsyncResponse ar) {
+ completeOperationsXmlGet(server.operationsGET(), ar);
}
/**
* Retrieve list of operations and actions supported by the server or device in XML format.
*
* @param operation path parameter to identify device and/or operation
- * @return A string containing an XML document conforming to both RFC8040 section 11.3.1 and page 84.
+ * @param ar {@link AsyncResponse} which needs to be completed
*/
@GET
@Path("/operations/{operation:.+}")
@Produces({ MediaTypes.APPLICATION_YANG_DATA_XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
- public String operationsXmlGET(@PathParam("operation") final String operation) {
- return operationsGET(operation).toXML();
+ public void operationsXmlGET(@PathParam("operation") final String operation, final AsyncResponse ar) {
+ completeOperationsXmlGet(server.operationsGET(operation), ar);
}
- private @NonNull OperationsGetResult operationsGET(final String operation) {
- final var content = server.operationsGET(operation);
- if (content == null) {
- throw new NotFoundException();
- }
- return content;
+ private static void completeOperationsXmlGet(final RestconfFuture<OperationsGetResult> future,
+ final AsyncResponse ar) {
+ completeOperationsGet(future, ar, OperationsGetResult::toXML);
+ }
+
+ private static void completeOperationsGet(final RestconfFuture<OperationsGetResult> future, final AsyncResponse ar,
+ final Function<OperationsGetResult, String> toString) {
+ future.addCallback(new JaxRsRestconfCallback<OperationsGetResult>(ar) {
+ @Override
+ Response transform(final OperationsGetResult result) {
+ return Response.ok().entity(toString.apply(result)).build();
+ }
+ });
}
/**
/**
* Get revision of IETF YANG Library module.
*
- * @return {@link NormalizedNodePayload}
+ * @param ar {@link AsyncResponse} which needs to be completed
*/
@GET
@Path("/yang-library-version")
MediaType.APPLICATION_XML,
MediaType.TEXT_XML
})
- public NormalizedNodePayload yangLibraryVersionGET() {
- return server.yangLibraryVersionGET();
+ public void yangLibraryVersionGET(@Suspended final AsyncResponse ar) {
+ server.yangLibraryVersionGET().addCallback(new JaxRsRestconfCallback<NormalizedNodePayload>(ar) {
+ @Override
+ Response transform(final NormalizedNodePayload result) {
+ return Response.ok().entity(result).build();
+ }
+ });
}
}
import java.net.URI;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.restconf.api.ApiPath;
import org.opendaylight.restconf.common.errors.RestconfFuture;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
RestconfFuture<DataPutResult> dataPUT(String identifier, ResourceBody body, Map<String, String> queryParameters);
/**
- * Return the set of supported RPCs supported by {@link #operationsPOST(URI, String, OperationInputBody)}.
+ * Return the set of supported RPCs supported by {@link #operationsPOST(URI, String, OperationInputBody)},
+ * as expressed in the <a href="https://www.rfc-editor.org/rfc/rfc8040#page-84">ietf-restconf.yang</a>
+ * {@code container operations} statement.
*
- * @return An {@link OperationsGetResult}
+ * @return A {@link RestconfFuture} completing with an {@link OperationsGetResult}
*/
- OperationsGetResult operationsGET();
+ RestconfFuture<OperationsGetResult> operationsGET();
/*
* Return the details about a particular operation supported by
* {@link #operationsPOST(URI, String, OperationInputBody)}, as expressed in the
- * <a href="https://www.rfc-editor.org/rfc/rfc8040#page-84>RFC8040<a> {@code container operations} statement.
+ * <a href="https://www.rfc-editor.org/rfc/rfc8040#page-84">ietf-restconfig.yang</a>
+ * {@code container operations} statement.
*
* @param operation An operation
- * @return An {@link OperationsContent}, or {@code null} if {@code operation} does not point to an {@code rpc}
+ * @return A {@link RestconfFuture} completing with an {@link OperationsGetResult}
*/
- // FIXME: 'operation' should really be an ApiIdentifier with non-null module, but we also support ang-ext:mount,
- // and hence it is a path right now
- // FIXME: use ApiPath instead of String
- @Nullable OperationsGetResult operationsGET(String operation);
+ RestconfFuture<OperationsGetResult> operationsGET(String operation);
/**
* Invoke an RPC operation, as defined in
* @param restconfURI Base URI of the request
* @param operation {@code <operation>} path, really an {@link ApiPath} to an {@code rpc}
* @param body RPC operation
- * @return A {@link RestconfFuture} of the {@link OperationOutput operation result}
+ * @return A {@link RestconfFuture} completing with {@link OperationOutput}
*/
// FIXME: 'operation' should really be an ApiIdentifier with non-null module, but we also support ang-ext:mount,
// and hence it is a path right now
* Return the revision of {@code ietf-yang-library} module implemented by this server, as defined in
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-3.3.3">RFC8040 {+restconf}/yang-library-version</a>.
*
- * @return A {@code yang-library-version} element
+ * @return A {@link RestconfFuture} completing with {@link NormalizedNodePayload} containing a single
+ * {@code yang-library-version} leaf element.
*/
- // FIXME: this is a simple coning-variadic return, similar to how OperationsContent is handled use a common
- // construct for both cases
- // FIXME: RestconfFuture if we transition to being used by restconf-client implementation
- NormalizedNodePayload yangLibraryVersionGET();
+ // FIXME: this is a simple encoding-variadic return, similar to how OperationsContent is handled use a common
+ // construct for both cases -- in this case it carries a yang.common.Revision
+ RestconfFuture<NormalizedNodePayload> yangLibraryVersionGET();
}
}
@Override
- public OperationsGetResult operationsGET() {
+ public RestconfFuture<OperationsGetResult> operationsGET() {
return operationsGET(databindProvider.currentContext().modelContext());
}
@Override
- public OperationsGetResult operationsGET(final String operation) {
+ public RestconfFuture<OperationsGetResult> operationsGET(final String operation) {
// get current module RPCs/actions by RPC/action name
final var inference = bindRequestPath(operation).inference();
if (inference.isEmpty()) {
final var stmt = inference.toSchemaInferenceStack().currentStatement();
if (stmt instanceof RpcEffectiveStatement rpc) {
- return new OperationsGetResult.Leaf(inference.getEffectiveModelContext(), rpc.argument());
+ return RestconfFuture.of(
+ new OperationsGetResult.Leaf(inference.getEffectiveModelContext(), rpc.argument()));
}
- LOG.debug("Operation '{}' resulted in non-RPC {}", operation, stmt);
- return null;
+ return RestconfFuture.failed(new RestconfDocumentedException("RPC not found",
+ ErrorType.PROTOCOL, ErrorTag.DATA_MISSING));
}
- private static @NonNull OperationsGetResult operationsGET(final EffectiveModelContext modelContext) {
+ private static @NonNull RestconfFuture<OperationsGetResult> operationsGET(
+ final EffectiveModelContext modelContext) {
final var modules = modelContext.getModuleStatements();
if (modules.isEmpty()) {
// No modules, or defensive return empty content
- return new OperationsGetResult.Container(modelContext, ImmutableSetMultimap.of());
+ return RestconfFuture.of(new OperationsGetResult.Container(modelContext, ImmutableSetMultimap.of()));
}
// RPCs by their XMLNamespace/Revision
.findFirst()
.ifPresent(row -> rpcs.putAll(QNameModule.create(entry.getKey(), row.getKey()), row.getValue()));
}
- return new OperationsGetResult.Container(modelContext, rpcs.build());
+ return RestconfFuture.of(new OperationsGetResult.Container(modelContext, rpcs.build()));
}
@Override
}
@Override
- public NormalizedNodePayload yangLibraryVersionGET() {
+ public RestconfFuture<NormalizedNodePayload> yangLibraryVersionGET() {
final var stack = SchemaInferenceStack.of(databindProvider.currentContext().modelContext());
- stack.enterYangData(YangApi.NAME);
- stack.enterDataTree(Restconf.QNAME);
- stack.enterDataTree(YANG_LIBRARY_VERSION);
- return new NormalizedNodePayload(stack.toInference(),
- ImmutableNodes.leafNode(YANG_LIBRARY_VERSION, YANG_LIBRARY_REVISION));
+ try {
+ stack.enterYangData(YangApi.NAME);
+ stack.enterDataTree(Restconf.QNAME);
+ stack.enterDataTree(YANG_LIBRARY_VERSION);
+ } catch (IllegalArgumentException e) {
+ return RestconfFuture.failed(new RestconfDocumentedException("RESTCONF is not available"));
+ }
+ return RestconfFuture.of(new NormalizedNodePayload(stack.toInference(),
+ ImmutableNodes.leafNode(YANG_LIBRARY_VERSION, YANG_LIBRARY_REVISION)));
}
private @NonNull InstanceIdentifierContext bindRequestPath(final String identifier) {
*/
package org.opendaylight.restconf.nb.jaxrs;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.List;
+import java.util.function.Consumer;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import org.eclipse.jdt.annotation.NonNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
+import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
@ExtendWith(MockitoExtension.class)
@Mock
UriInfo uriInfo;
@Mock
- AsyncResponse asyncResponse;
- @Mock
DOMDataBroker dataBroker;
@Mock
DOMActionService actionService;
DOMMountPointService mountPointService;
@Mock
DOMMountPoint mountPoint;
- @Captor
- ArgumentCaptor<Response> responseCaptor;
- @Captor
- ArgumentCaptor<RestconfDocumentedException> exceptionCaptor;
JaxRsRestconf restconf;
rpcService, actionService, mountPointService));
}
- @NonNull EffectiveModelContext modelContext() {
+ EffectiveModelContext modelContext() {
return JUKEBOX_SCHEMA;
}
+
+ static final NormalizedNode assertNormalizedNode(final int status, final Consumer<AsyncResponse> invocation) {
+ return assertEntity(NormalizedNodePayload.class, status, invocation).data();
+ }
+
+ static final <T> T assertEntity(final Class<T> expectedType, final int expectedStatus,
+ final Consumer<AsyncResponse> invocation) {
+ return assertInstanceOf(expectedType, assertEntity(expectedStatus, invocation));
+ }
+
+ static final Object assertEntity(final int expectedStatus, final Consumer<AsyncResponse> invocation) {
+ return assertResponse(expectedStatus, invocation).getEntity();
+ }
+
+ static final RestconfError assertError(final Consumer<AsyncResponse> invocation) {
+ final var errors = assertErrors(invocation);
+ assertEquals(1, errors.size());
+ final var error = errors.get(0);
+ assertNotNull(error);
+ return error;
+ }
+
+ static final List<RestconfError> assertErrors(final Consumer<AsyncResponse> invocation) {
+ final var ar = mock(AsyncResponse.class);
+ final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
+ doReturn(true).when(ar).resume(captor.capture());
+ invocation.accept(ar);
+ verify(ar).resume(any(RestconfDocumentedException.class));
+ return captor.getValue().getErrors();
+ }
+
+ static final Response assertResponse(final int expectedStatus, final Consumer<AsyncResponse> invocation) {
+ final var ar = mock(AsyncResponse.class);
+ final var captor = ArgumentCaptor.forClass(Response.class);
+ doReturn(true).when(ar).resume(captor.capture());
+ invocation.accept(ar);
+ verify(ar).resume(any(Response.class));
+ final var response = captor.getValue();
+ assertEquals(expectedStatus, response.getStatus());
+ return response;
+ }
}
import static org.junit.jupiter.api.Assertions.assertEquals;
-import org.eclipse.jdt.annotation.NonNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class Netconf822Test extends AbstractRestconfTest {
- private static final @NonNull EffectiveModelContext MODEL_CONTEXT =
+ private static final EffectiveModelContext MODEL_CONTEXT =
YangParserTestUtils.parseYangResourceDirectory("/nc822");
@Override
- @NonNull EffectiveModelContext modelContext() {
+ EffectiveModelContext modelContext() {
return MODEL_CONTEXT;
}
"foo:new" : [null],
"foo:new1" : [null]
}
- }""", restconf.operationsJsonGET());
+ }""", assertEntity(200, ar -> restconf.operationsJsonGET(ar)));
assertEquals("""
<operations xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf">
<new xmlns="foo"/>
<new1 xmlns="foo"/>
- </operations>""", restconf.operationsXmlGET());
+ </operations>""", assertEntity(200, ar -> restconf.operationsXmlGET(ar)));
}
@Test
void testOperationsContentByIdentifier() {
assertEquals("""
- { "foo:new1" : [null] }""", restconf.operationsJsonGET("foo:new1"));
+ { "foo:new1" : [null] }""", assertEntity(200, ar -> restconf.operationsJsonGET("foo:new1", ar)));
assertEquals("""
- <new1 xmlns="foo"/>""", restconf.operationsXmlGET("foo:new1"));
+ <new1 xmlns="foo"/>""", assertEntity(200, ar -> restconf.operationsXmlGET("foo:new1", ar)));
}
}
package org.opendaylight.restconf.nb.jaxrs;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
doReturn(immediateTrueFluentFuture())
.when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataDELETE("example-jukebox:jukebox", asyncResponse);
- assertEquals(204, responseCaptor.getValue().getStatus());
+ assertNull(assertEntity(204, ar -> restconf.dataDELETE("example-jukebox:jukebox", ar)));
}
@Test
.when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(true).when(tx).cancel();
- doReturn(true).when(asyncResponse).resume(exceptionCaptor.capture());
- restconf.dataDELETE("example-jukebox:jukebox", asyncResponse);
-
- final var errors = exceptionCaptor.getValue().getErrors();
- assertEquals(1, errors.size());
- final var error = errors.get(0);
+ final var error = assertError(ar -> restconf.dataDELETE("example-jukebox:jukebox", ar));
assertEquals(ErrorType.PROTOCOL, error.getErrorType());
assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
}
doReturn(immediateTrueFluentFuture())
.when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataDELETE("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", asyncResponse);
- assertEquals(204, responseCaptor.getValue().getStatus());
+ assertNull(assertEntity(204,
+ ar -> restconf.dataDELETE("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", ar)));
}
}
import static org.mockito.Mockito.doReturn;
import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
-import java.util.List;
import java.util.Optional;
import javax.ws.rs.core.MultivaluedHashMap;
import org.junit.jupiter.api.BeforeEach;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
-import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
doReturn(immediateFluentFuture(Optional.empty()))
.when(tx).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataGET("example-jukebox:jukebox", uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- assertEquals(EMPTY_JUKEBOX, ((NormalizedNodePayload) response.getEntity()).data());
+ assertEquals(EMPTY_JUKEBOX,
+ assertNormalizedNode(200, ar -> restconf.dataGET("example-jukebox:jukebox", uriInfo, ar)));
}
@Test
.when(tx)
.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of());
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataGET(uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
-
- final var data = assertInstanceOf(ContainerNode.class, ((NormalizedNodePayload) response.getEntity()).data());
+ final var data = assertInstanceOf(ContainerNode.class,
+ assertNormalizedNode(200, ar -> restconf.dataGET(uriInfo, ar)));
final var rootNodes = data.body();
assertEquals(1, rootNodes.size());
final var allDataChildren = assertInstanceOf(ContainerNode.class, rootNodes.iterator().next()).body();
doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataGET("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
-
// response must contain all child nodes from config and operational containers merged in one container
- final var data = assertInstanceOf(ContainerNode.class, ((NormalizedNodePayload) response.getEntity()).data());
+ final var data = assertInstanceOf(ContainerNode.class,
+ assertNormalizedNode(200, ar ->
+ restconf.dataGET("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo, ar)));
assertEquals(3, data.size());
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(LIBRARY_NID));
doReturn(immediateFluentFuture(Optional.empty()))
.when(tx).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
- doReturn(true).when(asyncResponse).resume(exceptionCaptor.capture());
- restconf.dataGET("example-jukebox:jukebox", uriInfo, asyncResponse);
-
- final var errors = exceptionCaptor.getValue().getErrors();
- assertEquals(1, errors.size());
- final var error = errors.get(0);
+ final var error = assertError(ar -> restconf.dataGET("example-jukebox:jukebox", uriInfo, ar));
assertEquals(ErrorType.PROTOCOL, error.getErrorType());
assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
assertEquals("Request could not be completed because the relevant data model content does not exist",
*/
@Test
void testReadDataConfigTest() {
- final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- parameters.put("content", List.of("config"));
+ final var parameters = new MultivaluedHashMap<String, String>();
+ parameters.putSingle("content", "config");
doReturn(parameters).when(uriInfo).getQueryParameters();
doReturn(immediateFluentFuture(Optional.of(CONFIG_JUKEBOX))).when(tx)
.read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataGET("example-jukebox:jukebox", uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
-
// response must contain only config data
- final var data = assertInstanceOf(ContainerNode.class, ((NormalizedNodePayload) response.getEntity()).data());
-
+ final var data = assertInstanceOf(ContainerNode.class,
+ assertNormalizedNode(200, ar -> restconf.dataGET("example-jukebox:jukebox", uriInfo, ar)));
// config data present
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(LIBRARY_NID));
-
// state data absent
assertNull(data.childByArg(PLAYLIST_NID));
}
doReturn(immediateFluentFuture(Optional.of(OPER_JUKEBOX))).when(tx)
.read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataGET("example-jukebox:jukebox", uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
-
- assertEquals(200, response.getStatus());
-
// response must contain only operational data
- final var data = assertInstanceOf(ContainerNode.class, ((NormalizedNodePayload) response.getEntity()).data());
-
+ final var data = assertInstanceOf(ContainerNode.class,
+ assertNormalizedNode(200, ar -> restconf.dataGET("example-jukebox:jukebox", uriInfo, ar)));
// state data present
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(PLAYLIST_NID));
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.doNothing;
doReturn(immediateFalseFluentFuture()).when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(immediateTrueFluentFuture()).when(tx).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataYangJsonPATCH(stringInputStream("""
- {
- "ietf-yang-patch:yang-patch" : {
- "patch-id" : "test patch id",
- "edit" : [
- {
- "edit-id" : "create data",
- "operation" : "create",
- "target" : "/example-jukebox:jukebox",
- "value" : {
- "jukebox" : {
- "player" : {
- "gap" : "0.2"
+ final var status = assertEntity(PatchStatusContext.class, 200,
+ ar -> restconf.dataYangJsonPATCH(stringInputStream("""
+ {
+ "ietf-yang-patch:yang-patch" : {
+ "patch-id" : "test patch id",
+ "edit" : [
+ {
+ "edit-id" : "create data",
+ "operation" : "create",
+ "target" : "/example-jukebox:jukebox",
+ "value" : {
+ "jukebox" : {
+ "player" : {
+ "gap" : "0.2"
+ }
+ }
}
- }
- }
- },
- {
- "edit-id" : "replace data",
- "operation" : "replace",
- "target" : "/example-jukebox:jukebox",
- "value" : {
- "jukebox" : {
- "player" : {
- "gap" : "0.3"
+ },
+ {
+ "edit-id" : "replace data",
+ "operation" : "replace",
+ "target" : "/example-jukebox:jukebox",
+ "value" : {
+ "jukebox" : {
+ "player" : {
+ "gap" : "0.3"
+ }
+ }
}
+ },
+ {
+ "edit-id" : "delete data",
+ "operation" : "delete",
+ "target" : "/example-jukebox:jukebox/player/gap"
}
- }
- },
- {
- "edit-id" : "delete data",
- "operation" : "delete",
- "target" : "/example-jukebox:jukebox/player/gap"
+ ]
}
- ]
- }"""), asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- final var status = assertInstanceOf(PatchStatusContext.class, response.getEntity());
+ }"""), ar));
assertTrue(status.ok());
final var edits = status.editCollection();
assertEquals(3, edits.size());
doReturn(immediateFalseFluentFuture()).when(tx).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
doReturn(true).when(tx).cancel();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataYangJsonPATCH(stringInputStream("""
- {
- "ietf-yang-patch:yang-patch" : {
- "patch-id" : "test patch id",
- "edit" : [
- {
- "edit-id" : "create data",
- "operation" : "create",
- "target" : "/example-jukebox:jukebox",
- "value" : {
- "jukebox" : {
- "player" : {
- "gap" : "0.2"
+ final var status = assertEntity(PatchStatusContext.class, 409, ar -> restconf.dataYangJsonPATCH(
+ stringInputStream("""
+ {
+ "ietf-yang-patch:yang-patch" : {
+ "patch-id" : "test patch id",
+ "edit" : [
+ {
+ "edit-id" : "create data",
+ "operation" : "create",
+ "target" : "/example-jukebox:jukebox",
+ "value" : {
+ "jukebox" : {
+ "player" : {
+ "gap" : "0.2"
+ }
+ }
}
+ },
+ {
+ "edit-id" : "remove data",
+ "operation" : "remove",
+ "target" : "/example-jukebox:jukebox/player/gap"
+ },
+ {
+ "edit-id" : "delete data",
+ "operation" : "delete",
+ "target" : "/example-jukebox:jukebox/player/gap"
}
- }
- },
- {
- "edit-id" : "remove data",
- "operation" : "remove",
- "target" : "/example-jukebox:jukebox/player/gap"
- },
- {
- "edit-id" : "delete data",
- "operation" : "delete",
- "target" : "/example-jukebox:jukebox/player/gap"
+ ]
}
- ]
- }
- }"""), asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(409, response.getStatus());
- final var status = assertInstanceOf(PatchStatusContext.class, response.getEntity());
+ }"""), ar));
assertFalse(status.ok());
final var edits = status.editCollection();
assertEquals(3, edits.size());
doReturn(immediateTrueFluentFuture()).when(tx).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataYangXmlPATCH(stringInputStream("""
- <yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
- <patch-id>test patch id</patch-id>
- <edit>
- <edit-id>create data</edit-id>
- <operation>create</operation>
- <target>/example-jukebox:jukebox</target>
- <value>
- <jukebox xmlns="http://example.com/ns/example-jukebox">
- <player>
- <gap>0.2</gap>
- </player>
- </jukebox>
- </value>
- </edit>
- <edit>
- <edit-id>replace data</edit-id>
- <operation>replace</operation>
- <target>/example-jukebox:jukebox</target>
- <value>
- <jukebox xmlns="http://example.com/ns/example-jukebox">
- <player>
- <gap>0.3</gap>
- </player>
- </jukebox>
- </value>
- </edit>
- <edit>
- <edit-id>delete data</edit-id>
- <operation>delete</operation>
- <target>/example-jukebox:jukebox/player/gap</target>
- </edit>
- </yang-patch>"""), asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- final var status = assertInstanceOf(PatchStatusContext.class, response.getEntity());
+ final var status = assertEntity(PatchStatusContext.class, 200,
+ ar -> restconf.dataYangXmlPATCH(stringInputStream("""
+ <yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
+ <patch-id>test patch id</patch-id>
+ <edit>
+ <edit-id>create data</edit-id>
+ <operation>create</operation>
+ <target>/example-jukebox:jukebox</target>
+ <value>
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>
+ </value>
+ </edit>
+ <edit>
+ <edit-id>replace data</edit-id>
+ <operation>replace</operation>
+ <target>/example-jukebox:jukebox</target>
+ <value>
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <player>
+ <gap>0.3</gap>
+ </player>
+ </jukebox>
+ </value>
+ </edit>
+ <edit>
+ <edit-id>delete data</edit-id>
+ <operation>delete</operation>
+ <target>/example-jukebox:jukebox/player/gap</target>
+ </edit>
+ </yang-patch>"""), ar));
assertTrue(status.ok());
assertNull(status.globalErrors());
final var edits = status.editCollection();
Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME)).build());
doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.postDataJSON(stringInputStream("""
- {
- "example-jukebox:jukebox" : {
- }
- }"""), uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(201, response.getStatus());
- assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox"), response.getLocation());
+ assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox"),
+ assertResponse(201, ar -> restconf.postDataJSON(stringInputStream("""
+ {
+ "example-jukebox:jukebox" : {
+ }
+ }"""), uriInfo, ar)).getLocation());
}
@Test
doNothing().when(tx).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.postDataJSON("example-jukebox:jukebox", stringInputStream("""
- {
- "example-jukebox:playlist" : {
- "name" : "name of band",
- "description" : "band description"
- }
- }"""), uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(201, response.getStatus());
assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox/playlist=name%20of%20band"),
- response.getLocation());
+ assertResponse(201, ar -> restconf.postDataJSON("example-jukebox:jukebox", stringInputStream("""
+ {
+ "example-jukebox:playlist" : {
+ "name" : "name of band",
+ "description" : "band description"
+ }
+ }"""), uriInfo, ar)).getLocation());
}
}
*/
package org.opendaylight.restconf.nb.jaxrs;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import java.util.Optional;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
doReturn(immediateTrueFluentFuture()).when(readTx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doNothing().when(rwTx).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataJsonPUT("example-jukebox:jukebox", uriInfo, stringInputStream("""
- {
- "example-jukebox:jukebox" : {
- "player": {
- "gap": "0.2"
- }
- }
- }"""), asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
+ assertNull(assertEntity(204, ar -> restconf.dataJsonPUT("example-jukebox:jukebox", uriInfo,
+ stringInputStream("""
+ {
+ "example-jukebox:jukebox" : {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }"""), ar)));
}
@Test
doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.dataXmlPUT("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox",
- uriInfo, stringInputStream("""
- <jukebox xmlns="http://example.com/ns/example-jukebox">
- <player>
- <gap>0.2</gap>
- </player>
- </jukebox>"""), asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
+ assertNull(assertEntity(204, ar -> restconf.dataXmlPUT(
+ "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo, stringInputStream("""
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>"""), ar)));
}
}
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
private static final EffectiveModelContext MODEL_CONTEXT = BindingRuntimeHelpers.createRuntimeContext(
Module1Data.class, Module2Data.class, NetworkTopology.class).getEffectiveModelContext();
- @Mock
- private DOMSchemaService schemaService;
-
@Override
EffectiveModelContext modelContext() {
return MODEL_CONTEXT;
@Test
void testOperationsJson() {
- final var operationsJSON = restconf.operationsJsonGET();
- assertEquals(EXPECTED_JSON, operationsJSON);
+ assertEquals(EXPECTED_JSON, assertEntity(200, ar -> restconf.operationsJsonGET(ar)));
}
@Test
void testOperationsXml() {
- final var operationsXML = restconf.operationsXmlGET();
- assertEquals(EXPECTED_XML, operationsXML);
+ assertEquals(EXPECTED_XML, assertEntity(200, ar -> restconf.operationsXmlGET(ar)));
}
private void mockMountPoint() {
+ final var schemaService = mock(DOMSchemaService.class);
doReturn(MODEL_CONTEXT).when(schemaService).getGlobalContext();
doReturn(Optional.of(schemaService)).when(mountPoint).getService(DOMSchemaService.class);
doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any());
@Test
void testMountPointOperationsJson() {
mockMountPoint();
- final var operationJSON = restconf.operationsJsonGET(DEVICE_ID);
- assertEquals(EXPECTED_JSON, operationJSON);
+ assertEquals(EXPECTED_JSON, assertEntity(200, ar -> restconf.operationsJsonGET(DEVICE_ID, ar)));
}
@Test
void testMountPointOperationsXml() {
mockMountPoint();
- final var operationXML = restconf.operationsXmlGET(DEVICE_ID);
- assertEquals(EXPECTED_XML, operationXML);
+ assertEquals(EXPECTED_XML, assertEntity(200, ar -> restconf.operationsXmlGET(DEVICE_ID, ar)));
}
@Test
void testMountPointSpecificOperationsJson() {
mockMountPoint();
- final var operationJSON = restconf.operationsJsonGET(DEVICE_RPC1_MODULE1_ID);
assertEquals("""
- { "module1:dummy-rpc1-module1" : [null] }""", operationJSON);
+ { "module1:dummy-rpc1-module1" : [null] }""",
+ assertEntity(200, ar -> restconf.operationsJsonGET(DEVICE_RPC1_MODULE1_ID, ar)));
}
@Test
void testMountPointSpecificOperationsXml() {
mockMountPoint();
- final var operationXML = restconf.operationsXmlGET(DEVICE_RPC1_MODULE1_ID);
assertEquals("""
- <dummy-rpc1-module1 xmlns="module:1"/>""", operationXML);
+ <dummy-rpc1-module1 xmlns="module:1"/>""",
+ assertEntity(200, ar -> restconf.operationsXmlGET(DEVICE_RPC1_MODULE1_ID, ar)));
}
}
*/
package org.opendaylight.restconf.nb.jaxrs;
+import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
-import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
doReturn(false).when(result).isEmpty();
prepNNC(result);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.operationsXmlPOST("invoke-rpc-module:rpc-test", stringInputStream("""
- <input xmlns="invoke:rpc:module"/>
- """), uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- final var entity = (NormalizedNodePayload) response.getEntity();
- assertSame(result, entity.data());
+ assertSame(result, assertNormalizedNode(200, ar -> restconf.operationsXmlPOST("invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ <input xmlns="invoke:rpc:module"/>"""), uriInfo, ar)));
}
@Test
doReturn(true).when(result).isEmpty();
prepNNC(result);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.operationsJsonPOST("invoke-rpc-module:rpc-test", stringInputStream("""
- {
- "invoke-rpc-module:input" : {
- }
- }"""), uriInfo, asyncResponse);
- assertEquals(204, responseCaptor.getValue().getStatus());
+ assertNull(assertEntity(204, ar -> restconf.operationsJsonPOST("invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ {
+ "invoke-rpc-module:input" : {
+ }
+ }"""), uriInfo, ar)));
}
@Test
- void invokeRpcTest() throws Exception {
+ void invokeRpcTest() {
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
.invokeRpc(RPC, INPUT);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.operationsXmlPOST("invoke-rpc-module:rpc-test", stringInputStream("""
- <input xmlns="invoke:rpc:module">
- <cont>
- <lf>test</lf>
- </cont>
- </input>"""), uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- final var payload = assertInstanceOf(NormalizedNodePayload.class, response.getEntity());
- assertEquals(OUTPUT, payload.data());
+ assertEquals(OUTPUT, assertNormalizedNode(200, ar -> restconf.operationsXmlPOST("invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ <input xmlns="invoke:rpc:module">
+ <cont>
+ <lf>test</lf>
+ </cont>
+ </input>"""), uriInfo, ar)));
}
@Test
"No implementation of RPC " + RPC + " available.");
doReturn(Futures.immediateFailedFuture(exception)).when(rpcService).invokeRpc(RPC, INPUT);
- doReturn(true).when(asyncResponse).resume(exceptionCaptor.capture());
- restconf.operationsJsonPOST("invoke-rpc-module:rpc-test", stringInputStream("""
- {
- "invoke-rpc-module:input" : {
- "cont" : {
- "lf" : "test"
- }
- }
- }"""), uriInfo, asyncResponse);
- final var errors = exceptionCaptor.getValue().getErrors();
- assertEquals(1, errors.size());
- final var error = errors.get(0);
+ final var error = assertError(ar -> restconf.operationsJsonPOST("invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ {
+ "invoke-rpc-module:input" : {
+ "cont" : {
+ "lf" : "test"
+ }
+ }
+ }"""), uriInfo, ar));
assertEquals("No implementation of RPC (invoke:rpc:module?revision=2013-12-03)rpc-test available.",
error.getErrorMessage());
assertEquals(ErrorType.RPC, error.getErrorType());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
.invokeRpc(RPC, INPUT);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.operationsJsonPOST("ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test",
+ assertEquals(OUTPUT, assertNormalizedNode(200,
+ ar -> restconf.operationsJsonPOST(
+ "ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test",
stringInputStream("""
{
"invoke-rpc-module:input" : {
"lf" : "test"
}
}
- }"""), uriInfo, asyncResponse);
- final var response = responseCaptor.getValue();
- assertEquals(200, response.getStatus());
- final var payload = assertInstanceOf(NormalizedNodePayload.class, response.getEntity());
- assertEquals(OUTPUT, payload.data());
+ }"""), uriInfo, ar)));
}
@Test
doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of(
QName.create("urn:ietf:params:xml:ns:yang:ietf-yang-library", "2016-06-21", "modules-state")));
- doReturn(true).when(asyncResponse).resume(exceptionCaptor.capture());
- restconf.operationsJsonPOST("ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test",
- stringInputStream("""
- {
- "invoke-rpc-module:input" : {
- }
- }"""), uriInfo, asyncResponse);
- final var errors = exceptionCaptor.getValue().getErrors();
- assertEquals(1, errors.size());
- final var error = errors.get(0);
+ final var error = assertError(
+ ar -> restconf.operationsJsonPOST(
+ "ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ {
+ "invoke-rpc-module:input" : {
+ }
+ }"""), uriInfo, ar));
assertEquals("RPC invocation is not available", error.getErrorMessage());
assertEquals(ErrorType.PROTOCOL, error.getErrorType());
assertEquals(ErrorTag.OPERATION_NOT_SUPPORTED, error.getErrorTag());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of())))
.when(rpcService).invokeRpc(RPC, INPUT);
- doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
- restconf.operationsJsonPOST("invoke-rpc-module:rpc-test", stringInputStream("""
- {
- "invoke-rpc-module:input" : {
- "cont" : {
- "lf" : "test"
- }
- }
- }"""), uriInfo, asyncResponse);
- final var payload = assertInstanceOf(NormalizedNodePayload.class, responseCaptor.getValue().getEntity());
- assertEquals(OUTPUT, payload.data());
+ assertEquals(OUTPUT, assertNormalizedNode(200, ar -> restconf.operationsJsonPOST("invoke-rpc-module:rpc-test",
+ stringInputStream("""
+ {
+ "invoke-rpc-module:input" : {
+ "cont" : {
+ "lf" : "test"
+ }
+ }
+ }"""), uriInfo, ar)));
}
private void prepNNC(final ContainerNode result) {
package org.opendaylight.restconf.nb.jaxrs;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
-import org.opendaylight.mdsal.dom.api.DOMActionService;
-import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcService;
-import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
-import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.Restconf;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
@ExtendWith(MockitoExtension.class)
-class RestconfYangLibraryVersionGetTest {
- @Mock
- private DOMDataBroker dataBroker;
- @Mock
- private DOMRpcService rpcService;
- @Mock
- private DOMActionService actionService;
- @Mock
- private DOMMountPointService mountPointService;
+class RestconfYangLibraryVersionGetTest extends AbstractRestconfTest {
+ @Override
+ EffectiveModelContext modelContext() {
+ return YangParserTestUtils.parseYangResourceDirectory("/restconf/impl");
+ }
@Test
void testLibraryVersion() {
- final var context = DatabindContext.ofModel(YangParserTestUtils.parseYangResourceDirectory("/restconf/impl"));
- final var restconfImpl = new JaxRsRestconf(new MdsalRestconfServer(() -> context, dataBroker, rpcService,
- actionService, mountPointService));
- final var libraryVersion = assertInstanceOf(LeafNode.class, restconfImpl.yangLibraryVersionGET().data());
- assertEquals("2019-01-04", libraryVersion.body());
+ assertEquals(ImmutableNodes.leafNode(QName.create(Restconf.QNAME, "yang-library-version"), "2019-01-04"),
+ assertNormalizedNode(200, ar -> restconf.yangLibraryVersionGET(ar)));
}
}