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.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
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;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@ExtendWith(MockitoExtension.class)
private static final NodeIdentifier LIBRARY_NID = new NodeIdentifier(LIBRARY_QNAME);
// config contains one child the same as in operational and one additional
- private static final ContainerNode CONFIG_JUKEBOX = Builders.containerBuilder()
+ private static final ContainerNode CONFIG_JUKEBOX = ImmutableNodes.newContainerBuilder()
.withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
.withChild(CONT_PLAYER)
- .withChild(Builders.containerBuilder().withNodeIdentifier(LIBRARY_NID).build())
+ .withChild(ImmutableNodes.newContainerBuilder().withNodeIdentifier(LIBRARY_NID).build())
.build();
// operational contains one child the same as in config and one additional
- private static final ContainerNode OPER_JUKEBOX = Builders.containerBuilder()
+ private static final ContainerNode OPER_JUKEBOX = ImmutableNodes.newContainerBuilder()
.withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
.withChild(CONT_PLAYER)
- .withChild(Builders.mapBuilder().withNodeIdentifier(PLAYLIST_NID).build())
+ .withChild(ImmutableNodes.newSystemMapBuilder().withNodeIdentifier(PLAYLIST_NID).build())
.build();
@Mock
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());
+ final var body = assertNormalizedBody(200, ar -> restconf.dataGET(JUKEBOX_API_PATH, uriInfo, ar));
+ assertEquals(EMPTY_JUKEBOX, body.data());
+ assertFormat("""
+ {
+ "example-jukebox:jukebox": {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }""", body::formatToJSON, true);
+ assertFormat("""
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>""", body::formatToXML, true);
}
@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 body = assertNormalizedBody(200, ar -> restconf.dataGET(uriInfo, ar));
+ final var data = assertInstanceOf(ContainerNode.class, body.data());
final var rootNodes = data.body();
assertEquals(1, rootNodes.size());
final var allDataChildren = assertInstanceOf(ContainerNode.class, rootNodes.iterator().next()).body();
assertEquals(3, allDataChildren.size());
+
+ assertFormat("""
+ {
+ "example-jukebox:jukebox": {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }""", body::formatToJSON, true);
+ assertFormat("""
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <library/>
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>
+ </data>""", body::formatToXML, true);
}
private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild data) {
- return Builders.containerBuilder()
+ return ImmutableNodes.newContainerBuilder()
.withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
.withChild(data)
.build();
doReturn(Optional.of(mountPoint)).when(mountPointService)
.getMountPoint(any(YangInstanceIdentifier.class));
- doReturn(Optional.of(FixedDOMSchemaService.of(JUKEBOX_SCHEMA))).when(mountPoint)
+ doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
.getService(DOMSchemaService.class);
doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
+ doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
+ doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.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 body = assertNormalizedBody(200, ar -> restconf.dataGET(
+ apiPath("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox"), uriInfo, ar));
+ final var data = assertInstanceOf(ContainerNode.class, body.data());
assertEquals(3, data.size());
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(LIBRARY_NID));
assertNotNull(data.childByArg(PLAYLIST_NID));
+
+ assertFormat("""
+ {
+ "example-jukebox:jukebox": {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }""", body::formatToJSON, true);
+ assertFormat("""
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <library/>
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>""", body::formatToXML, true);
}
@Test
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(JUKEBOX_API_PATH, 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 body = assertNormalizedBody(200, ar -> restconf.dataGET(JUKEBOX_API_PATH, uriInfo, ar));
+ final var data = assertInstanceOf(ContainerNode.class, body.data());
// config data present
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(LIBRARY_NID));
-
// state data absent
assertNull(data.childByArg(PLAYLIST_NID));
+
+ assertFormat("""
+ {
+ "example-jukebox:jukebox": {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }""", body::formatToJSON, true);
+ assertFormat("""
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <library/>
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>""", body::formatToXML, true);
}
/**
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 body = assertNormalizedBody(200, ar -> restconf.dataGET(JUKEBOX_API_PATH, uriInfo, ar));
+ final var data = assertInstanceOf(ContainerNode.class, body.data());
// state data present
assertNotNull(data.childByArg(CONT_PLAYER.name()));
assertNotNull(data.childByArg(PLAYLIST_NID));
// config data absent
assertNull(data.childByArg(LIBRARY_NID));
+
+ assertFormat("""
+ {
+ "example-jukebox:jukebox": {
+ "player": {
+ "gap": "0.2"
+ }
+ }
+ }""", body::formatToJSON, true);
+ assertFormat("""
+ <jukebox xmlns="http://example.com/ns/example-jukebox">
+ <player>
+ <gap>0.2</gap>
+ </player>
+ </jukebox>""", body::formatToXML, true);
}
}