2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertThrows;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.mock;
20 import static org.opendaylight.restconf.common.patch.PatchEditOperation.CREATE;
21 import static org.opendaylight.restconf.common.patch.PatchEditOperation.DELETE;
22 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REMOVE;
23 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REPLACE;
24 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
25 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
26 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
29 import java.util.Collection;
30 import java.util.List;
31 import java.util.Optional;
33 import javax.ws.rs.container.AsyncResponse;
34 import javax.ws.rs.core.MultivaluedHashMap;
35 import javax.ws.rs.core.MultivaluedMap;
36 import javax.ws.rs.core.Response;
37 import javax.ws.rs.core.UriBuilder;
38 import javax.ws.rs.core.UriInfo;
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.mockito.ArgumentCaptor;
43 import org.mockito.Mock;
44 import org.mockito.junit.MockitoJUnitRunner;
45 import org.opendaylight.mdsal.common.api.CommitInfo;
46 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
47 import org.opendaylight.mdsal.dom.api.DOMActionService;
48 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
49 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
50 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
51 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
52 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
53 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
54 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
55 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
56 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
57 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
58 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
59 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
60 import org.opendaylight.restconf.common.patch.PatchContext;
61 import org.opendaylight.restconf.common.patch.PatchEntity;
62 import org.opendaylight.restconf.common.patch.PatchStatusContext;
63 import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
64 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
65 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
66 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
67 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
68 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
69 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
70 import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
71 import org.opendaylight.yangtools.yang.common.ErrorTag;
72 import org.opendaylight.yangtools.yang.common.ErrorType;
73 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
74 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
75 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
76 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
77 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
78 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
79 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
80 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
82 @RunWith(MockitoJUnitRunner.StrictStubs.class)
83 public class RestconfDataServiceImplTest extends AbstractJukeboxTest {
84 private ContainerNode buildBaseCont;
85 private ContainerNode buildBaseContConfig;
86 private ContainerNode buildBaseContOperational;
87 private RestconfDataServiceImpl dataService;
88 private ContainerNode buildPlayerCont;
89 private ContainerNode buildLibraryCont;
90 private MapNode buildPlaylistList;
93 private DOMTransactionChain domTransactionChain;
95 private UriInfo uriInfo;
97 private DOMDataTreeReadWriteTransaction readWrite;
99 private DOMDataTreeReadTransaction read;
101 private DOMDataTreeWriteTransaction write;
103 private DOMMountPointService mountPointService;
105 private DOMMountPoint mountPoint;
107 private DOMDataBroker mountDataBroker;
109 private NetconfDataTreeService netconfService;
111 private DOMActionService actionService;
113 private RestconfStreamsSubscriptionService delegRestconfSubscrService;
115 private MultivaluedMap<String, String> queryParamenters;
117 private AsyncResponse asyncResponse;
120 public void setUp() throws Exception {
121 doReturn(Set.of()).when(queryParamenters).entrySet();
122 doReturn(queryParamenters).when(uriInfo).getQueryParameters();
124 buildPlayerCont = Builders.containerBuilder()
125 .withNodeIdentifier(new NodeIdentifier(PLAYER_QNAME))
129 buildLibraryCont = Builders.containerBuilder()
130 .withNodeIdentifier(new NodeIdentifier(LIBRARY_QNAME))
133 buildPlaylistList = Builders.mapBuilder()
134 .withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME))
137 buildBaseCont = Builders.containerBuilder()
138 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
139 .withChild(buildPlayerCont)
142 // config contains one child the same as in operational and one additional
143 buildBaseContConfig = Builders.containerBuilder()
144 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
145 .withChild(buildPlayerCont)
146 .withChild(buildLibraryCont)
149 // operational contains one child the same as in config and one additional
150 buildBaseContOperational = Builders.containerBuilder()
151 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
152 .withChild(buildPlayerCont)
153 .withChild(buildPlaylistList)
156 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
158 DOMDataBroker mockDataBroker = mock(DOMDataBroker.class);
159 doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
160 doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
162 dataService = new RestconfDataServiceImpl(() -> DatabindContext.ofModel(JUKEBOX_SCHEMA), mockDataBroker,
163 mountPointService, delegRestconfSubscrService, actionService, new StreamsConfiguration(0, 1, 0, false));
164 doReturn(Optional.of(mountPoint)).when(mountPointService)
165 .getMountPoint(any(YangInstanceIdentifier.class));
166 doReturn(Optional.of(FixedDOMSchemaService.of(JUKEBOX_SCHEMA))).when(mountPoint)
167 .getService(DOMSchemaService.class);
168 doReturn(Optional.of(mountDataBroker)).when(mountPoint).getService(DOMDataBroker.class);
169 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
170 doReturn(read).when(mountDataBroker).newReadOnlyTransaction();
171 doReturn(readWrite).when(mountDataBroker).newReadWriteTransaction();
175 public void testReadData() {
176 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
177 doReturn(immediateFluentFuture(Optional.of(buildBaseCont))).when(read)
178 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
179 doReturn(immediateFluentFuture(Optional.empty()))
180 .when(read).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
181 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
182 assertNotNull(response);
183 assertEquals(200, response.getStatus());
184 assertEquals(buildBaseCont, ((NormalizedNodePayload) response.getEntity()).getData());
188 public void testReadRootData() {
189 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
190 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContConfig))))
192 .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of());
193 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContOperational))))
195 .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of());
196 final Response response = dataService.readData(uriInfo);
197 assertNotNull(response);
198 assertEquals(200, response.getStatus());
200 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
201 assertTrue(data instanceof ContainerNode);
202 final Collection<DataContainerChild> rootNodes = ((ContainerNode) data).body();
203 assertEquals(1, rootNodes.size());
204 final Collection<DataContainerChild> allDataChildren = ((ContainerNode) rootNodes.iterator().next()).body();
205 assertEquals(3, allDataChildren.size());
208 private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild data) {
209 return Builders.containerBuilder()
210 .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
216 * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
217 * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
220 public void testReadDataMountPoint() {
221 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
222 doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
223 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
224 doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
225 .read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
227 final Response response = dataService.readData(
228 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo);
230 assertNotNull(response);
231 assertEquals(200, response.getStatus());
233 // response must contain all child nodes from config and operational containers merged in one container
234 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
235 assertTrue(data instanceof ContainerNode);
236 assertEquals(3, ((ContainerNode) data).size());
237 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
238 assertNotNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
239 assertNotNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
243 public void testReadDataNoData() {
244 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
245 doReturn(immediateFluentFuture(Optional.empty()))
246 .when(read).read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
247 doReturn(immediateFluentFuture(Optional.empty()))
248 .when(read).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
250 final var errors = assertThrows(RestconfDocumentedException.class,
251 () -> dataService.readData("example-jukebox:jukebox", uriInfo)).getErrors();
252 assertEquals(1, errors.size());
253 final var error = errors.get(0);
254 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
255 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
256 assertEquals("Request could not be completed because the relevant data model content does not exist",
257 error.getErrorMessage());
261 * Read data from config datastore according to content parameter.
264 public void testReadDataConfigTest() {
265 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
266 parameters.put("content", List.of("config"));
268 doReturn(parameters).when(uriInfo).getQueryParameters();
269 doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
270 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
272 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
274 assertNotNull(response);
275 assertEquals(200, response.getStatus());
277 // response must contain only config data
278 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
280 // config data present
281 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
282 assertNotNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
285 assertNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
289 * Read data from operational datastore according to content parameter.
292 public void testReadDataOperationalTest() {
293 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
294 parameters.put("content", List.of("nonconfig"));
296 doReturn(parameters).when(uriInfo).getQueryParameters();
297 doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
298 .read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
300 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
302 assertNotNull(response);
303 assertEquals(200, response.getStatus());
305 // response must contain only operational data
306 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
308 // state data present
309 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
310 assertNotNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
312 // config data absent
313 assertNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
317 public void testPutData() {
318 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
319 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
321 doReturn(immediateTrueFluentFuture()).when(read)
322 .exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
323 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, payload.getData());
324 final Response response = dataService.putData(null, payload, uriInfo);
325 assertNotNull(response);
326 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
330 public void testPutDataWithMountPoint() {
331 final InstanceIdentifierContext iidContext =
332 InstanceIdentifierContext.ofMountPointPath(mountPoint, JUKEBOX_SCHEMA, JUKEBOX_IID);
333 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
335 doReturn(immediateTrueFluentFuture()).when(read)
336 .exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
337 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, payload.getData());
338 final Response response = dataService.putData(null, payload, uriInfo);
339 assertNotNull(response);
340 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
344 public void testPostData() {
345 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
346 final var node = JUKEBOX_IID.node(BAND_ENTRY.name());
347 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
348 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
349 doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
351 final var response = dataService.postData(NormalizedNodePayload.of(
352 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID),
353 Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME)).withChild(BAND_ENTRY).build()),
355 assertEquals(201, response.getStatus());
356 assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox"), response.getLocation());
360 public void testPostMapEntryData() {
361 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
362 final var node = PLAYLIST_IID.node(BAND_ENTRY.name());
363 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
364 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
365 doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
367 final var response = dataService.postData(NormalizedNodePayload.of(
368 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, PLAYLIST_IID),
369 Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME)).withChild(BAND_ENTRY).build()),
371 assertEquals(201, response.getStatus());
372 assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox/playlist=name%20of%20band"),
373 response.getLocation());
377 public void testDeleteData() {
378 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
379 doReturn(immediateTrueFluentFuture())
380 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
381 final var captor = ArgumentCaptor.forClass(Response.class);
382 doReturn(true).when(asyncResponse).resume(captor.capture());
383 dataService.deleteData("example-jukebox:jukebox", asyncResponse);
385 assertEquals(204, captor.getValue().getStatus());
389 public void testDeleteDataNotExisting() {
390 doReturn(immediateFalseFluentFuture())
391 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
392 final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
393 doReturn(true).when(asyncResponse).resume(captor.capture());
394 dataService.deleteData("example-jukebox:jukebox", asyncResponse);
396 final var errors = captor.getValue().getErrors();
397 assertEquals(1, errors.size());
398 final var error = errors.get(0);
399 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
400 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
404 * Test of deleting data on mount point.
407 public void testDeleteDataMountPoint() {
408 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
409 doReturn(immediateTrueFluentFuture())
410 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
411 final var captor = ArgumentCaptor.forClass(Response.class);
412 doReturn(true).when(asyncResponse).resume(captor.capture());
413 dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", asyncResponse);
415 assertEquals(204, captor.getValue().getStatus());
419 public void testPatchData() {
420 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
421 final PatchContext patch = new PatchContext(iidContext, List.of(
422 new PatchEntity("create data", CREATE, JUKEBOX_IID, buildBaseCont),
423 new PatchEntity("replace data", REPLACE, JUKEBOX_IID, buildBaseCont),
424 new PatchEntity("delete data", DELETE, GAP_IID)), "test patch id");
426 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
427 doReturn(immediateFalseFluentFuture())
428 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
429 doReturn(immediateTrueFluentFuture())
430 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
431 final PatchStatusContext status = dataService.patchData(patch);
432 assertTrue(status.isOk());
433 assertEquals(3, status.getEditCollection().size());
434 assertEquals("replace data", status.getEditCollection().get(1).getEditId());
438 public void testPatchDataMountPoint() throws Exception {
439 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofMountPointPath(mountPoint,
440 JUKEBOX_SCHEMA, JUKEBOX_IID);
441 final PatchContext patch = new PatchContext(iidContext, List.of(
442 new PatchEntity("create data", CREATE, JUKEBOX_IID, buildBaseCont),
443 new PatchEntity("replace data", REPLACE, JUKEBOX_IID, buildBaseCont),
444 new PatchEntity("delete data", DELETE, GAP_IID)), "test patch id");
446 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
447 doReturn(immediateFalseFluentFuture())
448 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
449 doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
451 final PatchStatusContext status = dataService.patchData(patch);
452 assertTrue(status.isOk());
453 assertEquals(3, status.getEditCollection().size());
454 assertNull(status.getGlobalErrors());
458 public void testPatchDataDeleteNotExist() {
459 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
460 final PatchContext patch = new PatchContext(iidContext, List.of(
461 new PatchEntity("create data", CREATE, JUKEBOX_IID, buildBaseCont),
462 new PatchEntity("remove data", REMOVE, GAP_IID),
463 new PatchEntity("delete data", DELETE, GAP_IID)), "test patch id");
465 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
466 doReturn(immediateFalseFluentFuture())
467 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
468 doReturn(immediateFalseFluentFuture())
469 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
470 doReturn(true).when(readWrite).cancel();
471 final PatchStatusContext status = dataService.patchData(patch);
473 assertFalse(status.isOk());
474 assertEquals(3, status.getEditCollection().size());
475 assertTrue(status.getEditCollection().get(0).isOk());
476 assertTrue(status.getEditCollection().get(1).isOk());
477 assertFalse(status.getEditCollection().get(2).isOk());
478 assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
479 final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
480 assertEquals("Data does not exist", errorMessage);
484 public void testGetRestconfStrategy() {
485 RestconfStrategy restconfStrategy = dataService.getRestconfStrategy(mountPoint);
486 assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
488 doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
489 restconfStrategy = dataService.getRestconfStrategy(mountPoint);
490 assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);
494 public void testValidInputData() {
495 RestconfDataServiceImpl.validInputData(true, NormalizedNodePayload.of(
496 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID), GAP_LEAF));
500 public void testValidTopLevelNodeName() {
501 RestconfDataServiceImpl.validTopLevelNodeName(GAP_IID, NormalizedNodePayload.of(
502 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID), GAP_LEAF));
503 RestconfDataServiceImpl.validTopLevelNodeName(JUKEBOX_IID, NormalizedNodePayload.of(
504 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID), EMPTY_JUKEBOX));
508 public void testValidTopLevelNodeNamePathEmpty() {
509 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID);
510 final var payload = NormalizedNodePayload.of(iidContext, GAP_LEAF);
512 // FIXME: more asserts
513 assertThrows(RestconfDocumentedException.class,
514 () -> RestconfDataServiceImpl.validTopLevelNodeName(YangInstanceIdentifier.of(), payload));
518 public void testValidTopLevelNodeNameWrongTopIdentifier() {
519 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID);
520 final var payload = NormalizedNodePayload.of(iidContext, GAP_LEAF);
522 // FIXME: more asserts
523 assertThrows(RestconfDocumentedException.class,
524 () -> RestconfDataServiceImpl.validTopLevelNodeName(GAP_IID.getAncestor(1), payload));
528 public void testValidateListKeysEqualityInPayloadAndUri() {
529 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, YangInstanceIdentifier.builder()
531 .node(PLAYLIST_QNAME)
532 .nodeWithKey(PLAYLIST_QNAME, NAME_QNAME, "name of band")
534 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, BAND_ENTRY);
535 RestconfDataServiceImpl.validateListKeysEqualityInPayloadAndUri(payload);