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.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
21 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
22 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Optional;
29 import javax.ws.rs.container.AsyncResponse;
30 import javax.ws.rs.core.MultivaluedHashMap;
31 import javax.ws.rs.core.MultivaluedMap;
32 import javax.ws.rs.core.Response;
33 import javax.ws.rs.core.UriBuilder;
34 import javax.ws.rs.core.UriInfo;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.mockito.ArgumentCaptor;
39 import org.mockito.Mock;
40 import org.mockito.junit.MockitoJUnitRunner;
41 import org.opendaylight.mdsal.common.api.CommitInfo;
42 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
43 import org.opendaylight.mdsal.dom.api.DOMActionService;
44 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
45 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
46 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
47 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
48 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
49 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
50 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
51 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
52 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
53 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
54 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
55 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
56 import org.opendaylight.restconf.common.patch.PatchContext;
57 import org.opendaylight.restconf.common.patch.PatchEntity;
58 import org.opendaylight.restconf.common.patch.PatchStatusContext;
59 import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
60 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
61 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
62 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
63 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
64 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
65 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
66 import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
68 import org.opendaylight.yangtools.yang.common.ErrorTag;
69 import org.opendaylight.yangtools.yang.common.ErrorType;
70 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
71 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
72 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
73 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
74 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
75 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
76 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
77 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
79 @RunWith(MockitoJUnitRunner.StrictStubs.class)
80 public class RestconfDataServiceImplTest extends AbstractJukeboxTest {
81 private ContainerNode buildBaseCont;
82 private ContainerNode buildBaseContConfig;
83 private ContainerNode buildBaseContOperational;
84 private RestconfDataServiceImpl dataService;
85 private ContainerNode buildPlayerCont;
86 private ContainerNode buildLibraryCont;
87 private MapNode buildPlaylistList;
90 private DOMTransactionChain domTransactionChain;
92 private UriInfo uriInfo;
94 private DOMDataTreeReadWriteTransaction readWrite;
96 private DOMDataTreeReadTransaction read;
98 private DOMDataTreeWriteTransaction write;
100 private DOMMountPointService mountPointService;
102 private DOMMountPoint mountPoint;
104 private DOMDataBroker mountDataBroker;
106 private NetconfDataTreeService netconfService;
108 private DOMActionService actionService;
110 private RestconfStreamsSubscriptionService delegRestconfSubscrService;
112 private MultivaluedMap<String, String> queryParamenters;
114 private AsyncResponse asyncResponse;
117 public void setUp() throws Exception {
118 doReturn(Set.of()).when(queryParamenters).entrySet();
119 doReturn(queryParamenters).when(uriInfo).getQueryParameters();
121 buildPlayerCont = Builders.containerBuilder()
122 .withNodeIdentifier(new NodeIdentifier(PLAYER_QNAME))
126 buildLibraryCont = Builders.containerBuilder()
127 .withNodeIdentifier(new NodeIdentifier(LIBRARY_QNAME))
130 buildPlaylistList = Builders.mapBuilder()
131 .withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME))
134 buildBaseCont = Builders.containerBuilder()
135 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
136 .withChild(buildPlayerCont)
139 // config contains one child the same as in operational and one additional
140 buildBaseContConfig = Builders.containerBuilder()
141 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
142 .withChild(buildPlayerCont)
143 .withChild(buildLibraryCont)
146 // operational contains one child the same as in config and one additional
147 buildBaseContOperational = Builders.containerBuilder()
148 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
149 .withChild(buildPlayerCont)
150 .withChild(buildPlaylistList)
153 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
155 DOMDataBroker mockDataBroker = mock(DOMDataBroker.class);
156 doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
157 doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
159 dataService = new RestconfDataServiceImpl(() -> DatabindContext.ofModel(JUKEBOX_SCHEMA), mockDataBroker,
160 mountPointService, delegRestconfSubscrService, actionService, new StreamsConfiguration(0, 1, 0, false));
161 doReturn(Optional.of(mountPoint)).when(mountPointService)
162 .getMountPoint(any(YangInstanceIdentifier.class));
163 doReturn(Optional.of(FixedDOMSchemaService.of(JUKEBOX_SCHEMA))).when(mountPoint)
164 .getService(DOMSchemaService.class);
165 doReturn(Optional.of(mountDataBroker)).when(mountPoint).getService(DOMDataBroker.class);
166 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
167 doReturn(read).when(mountDataBroker).newReadOnlyTransaction();
168 doReturn(readWrite).when(mountDataBroker).newReadWriteTransaction();
172 public void testReadData() {
173 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
174 doReturn(immediateFluentFuture(Optional.of(buildBaseCont))).when(read)
175 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
176 doReturn(immediateFluentFuture(Optional.empty()))
177 .when(read).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
178 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
179 assertNotNull(response);
180 assertEquals(200, response.getStatus());
181 assertEquals(buildBaseCont, ((NormalizedNodePayload) response.getEntity()).getData());
185 public void testReadRootData() {
186 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
187 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContConfig))))
189 .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of());
190 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContOperational))))
192 .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of());
193 final Response response = dataService.readData(uriInfo);
194 assertNotNull(response);
195 assertEquals(200, response.getStatus());
197 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
198 assertTrue(data instanceof ContainerNode);
199 final Collection<DataContainerChild> rootNodes = ((ContainerNode) data).body();
200 assertEquals(1, rootNodes.size());
201 final Collection<DataContainerChild> allDataChildren = ((ContainerNode) rootNodes.iterator().next()).body();
202 assertEquals(3, allDataChildren.size());
205 private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild data) {
206 return Builders.containerBuilder()
207 .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
213 * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
214 * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
217 public void testReadDataMountPoint() {
218 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
219 doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
220 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
221 doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
222 .read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
224 final Response response = dataService.readData(
225 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo);
227 assertNotNull(response);
228 assertEquals(200, response.getStatus());
230 // response must contain all child nodes from config and operational containers merged in one container
231 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
232 assertTrue(data instanceof ContainerNode);
233 assertEquals(3, ((ContainerNode) data).size());
234 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
235 assertNotNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
236 assertNotNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
240 public void testReadDataNoData() {
241 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
242 doReturn(immediateFluentFuture(Optional.empty()))
243 .when(read).read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
244 doReturn(immediateFluentFuture(Optional.empty()))
245 .when(read).read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
247 final var errors = assertThrows(RestconfDocumentedException.class,
248 () -> dataService.readData("example-jukebox:jukebox", uriInfo)).getErrors();
249 assertEquals(1, errors.size());
250 final var error = errors.get(0);
251 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
252 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
253 assertEquals("Request could not be completed because the relevant data model content does not exist",
254 error.getErrorMessage());
258 * Read data from config datastore according to content parameter.
261 public void testReadDataConfigTest() {
262 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
263 parameters.put("content", List.of("config"));
265 doReturn(parameters).when(uriInfo).getQueryParameters();
266 doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
267 .read(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
269 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
271 assertNotNull(response);
272 assertEquals(200, response.getStatus());
274 // response must contain only config data
275 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
277 // config data present
278 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
279 assertNotNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
282 assertNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
286 * Read data from operational datastore according to content parameter.
289 public void testReadDataOperationalTest() {
290 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
291 parameters.put("content", List.of("nonconfig"));
293 doReturn(parameters).when(uriInfo).getQueryParameters();
294 doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
295 .read(LogicalDatastoreType.OPERATIONAL, JUKEBOX_IID);
297 final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
299 assertNotNull(response);
300 assertEquals(200, response.getStatus());
302 // response must contain only operational data
303 final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
305 // state data present
306 assertNotNull(((ContainerNode) data).childByArg(buildPlayerCont.name()));
307 assertNotNull(((ContainerNode) data).childByArg(buildPlaylistList.name()));
309 // config data absent
310 assertNull(((ContainerNode) data).childByArg(buildLibraryCont.name()));
314 public void testPutData() {
315 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
316 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
318 doReturn(immediateTrueFluentFuture()).when(read)
319 .exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
320 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, payload.getData());
321 final Response response = dataService.putData(null, payload, uriInfo);
322 assertNotNull(response);
323 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
327 public void testPutDataWithMountPoint() {
328 final InstanceIdentifierContext iidContext =
329 InstanceIdentifierContext.ofMountPointPath(mountPoint, JUKEBOX_SCHEMA, JUKEBOX_IID);
330 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
332 doReturn(immediateTrueFluentFuture()).when(read)
333 .exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
334 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, payload.getData());
335 final Response response = dataService.putData(null, payload, uriInfo);
336 assertNotNull(response);
337 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
341 public void testPostData() {
342 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
343 final var node = JUKEBOX_IID.node(BAND_ENTRY.name());
344 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
345 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
346 doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
348 final var response = dataService.postData(NormalizedNodePayload.of(
349 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID),
350 Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME)).withChild(BAND_ENTRY).build()),
352 assertEquals(201, response.getStatus());
353 assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox"), response.getLocation());
357 public void testPostMapEntryData() {
358 doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
359 final var node = PLAYLIST_IID.node(BAND_ENTRY.name());
360 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
361 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
362 doReturn(UriBuilder.fromUri("http://localhost:8181/rests/")).when(uriInfo).getBaseUriBuilder();
364 final var response = dataService.postData(NormalizedNodePayload.of(
365 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, PLAYLIST_IID),
366 Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME)).withChild(BAND_ENTRY).build()),
368 assertEquals(201, response.getStatus());
369 assertEquals(URI.create("http://localhost:8181/rests/data/example-jukebox:jukebox/playlist=name%20of%20band"),
370 response.getLocation());
374 public void testDeleteData() {
375 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
376 doReturn(immediateTrueFluentFuture())
377 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
378 final var captor = ArgumentCaptor.forClass(Response.class);
379 doReturn(true).when(asyncResponse).resume(captor.capture());
380 dataService.deleteData("example-jukebox:jukebox", asyncResponse);
382 assertEquals(204, captor.getValue().getStatus());
386 public void testDeleteDataNotExisting() {
387 doReturn(immediateFalseFluentFuture())
388 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
389 final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
390 doReturn(true).when(asyncResponse).resume(captor.capture());
391 dataService.deleteData("example-jukebox:jukebox", asyncResponse);
393 final var errors = captor.getValue().getErrors();
394 assertEquals(1, errors.size());
395 final var error = errors.get(0);
396 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
397 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
401 * Test of deleting data on mount point.
404 public void testDeleteDataMountPoint() {
405 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
406 doReturn(immediateTrueFluentFuture())
407 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
408 final var captor = ArgumentCaptor.forClass(Response.class);
409 doReturn(true).when(asyncResponse).resume(captor.capture());
410 dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", asyncResponse);
412 assertEquals(204, captor.getValue().getStatus());
416 public void testPatchData() {
417 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
418 final PatchContext patch = new PatchContext(iidContext, List.of(
419 new PatchEntity("create data", Operation.Create, JUKEBOX_IID, buildBaseCont),
420 new PatchEntity("replace data", Operation.Replace, JUKEBOX_IID, buildBaseCont),
421 new PatchEntity("delete data", Operation.Delete, GAP_IID)), "test patch id");
423 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
424 doReturn(immediateFalseFluentFuture())
425 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
426 doReturn(immediateTrueFluentFuture())
427 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
428 final PatchStatusContext status = dataService.patchData(patch);
429 assertTrue(status.ok());
430 assertEquals(3, status.editCollection().size());
431 assertEquals("replace data", status.editCollection().get(1).getEditId());
435 public void testPatchDataMountPoint() throws Exception {
436 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofMountPointPath(mountPoint,
437 JUKEBOX_SCHEMA, JUKEBOX_IID);
438 final PatchContext patch = new PatchContext(iidContext, List.of(
439 new PatchEntity("create data", Operation.Create, JUKEBOX_IID, buildBaseCont),
440 new PatchEntity("replace data", Operation.Replace, JUKEBOX_IID, buildBaseCont),
441 new PatchEntity("delete data", Operation.Delete, GAP_IID)), "test patch id");
443 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
444 doReturn(immediateFalseFluentFuture())
445 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
446 doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
448 final PatchStatusContext status = dataService.patchData(patch);
449 assertTrue(status.ok());
450 assertEquals(3, status.editCollection().size());
451 assertNull(status.globalErrors());
455 public void testPatchDataDeleteNotExist() {
456 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID);
457 final PatchContext patch = new PatchContext(iidContext, List.of(
458 new PatchEntity("create data", Operation.Create, JUKEBOX_IID, buildBaseCont),
459 new PatchEntity("remove data", Operation.Remove, GAP_IID),
460 new PatchEntity("delete data", Operation.Delete, GAP_IID)), "test patch id");
462 doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, GAP_IID);
463 doReturn(immediateFalseFluentFuture())
464 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
465 doReturn(immediateFalseFluentFuture())
466 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
467 doReturn(true).when(readWrite).cancel();
468 final PatchStatusContext status = dataService.patchData(patch);
470 assertFalse(status.ok());
471 assertEquals(3, status.editCollection().size());
472 assertTrue(status.editCollection().get(0).isOk());
473 assertTrue(status.editCollection().get(1).isOk());
474 assertFalse(status.editCollection().get(2).isOk());
475 assertFalse(status.editCollection().get(2).getEditErrors().isEmpty());
476 final String errorMessage = status.editCollection().get(2).getEditErrors().get(0).getErrorMessage();
477 assertEquals("Data does not exist", errorMessage);
481 public void testGetRestconfStrategy() {
482 RestconfStrategy restconfStrategy = dataService.getRestconfStrategy(mountPoint);
483 assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
485 doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
486 restconfStrategy = dataService.getRestconfStrategy(mountPoint);
487 assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);
491 public void testValidInputData() {
492 RestconfDataServiceImpl.validInputData(true, NormalizedNodePayload.of(
493 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID), GAP_LEAF));
497 public void testValidTopLevelNodeName() {
498 RestconfDataServiceImpl.validTopLevelNodeName(GAP_IID, NormalizedNodePayload.of(
499 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID), GAP_LEAF));
500 RestconfDataServiceImpl.validTopLevelNodeName(JUKEBOX_IID, NormalizedNodePayload.of(
501 InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, JUKEBOX_IID), EMPTY_JUKEBOX));
505 public void testValidTopLevelNodeNamePathEmpty() {
506 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID);
507 final var payload = NormalizedNodePayload.of(iidContext, GAP_LEAF);
509 // FIXME: more asserts
510 assertThrows(RestconfDocumentedException.class,
511 () -> RestconfDataServiceImpl.validTopLevelNodeName(YangInstanceIdentifier.of(), payload));
515 public void testValidTopLevelNodeNameWrongTopIdentifier() {
516 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, GAP_IID);
517 final var payload = NormalizedNodePayload.of(iidContext, GAP_LEAF);
519 // FIXME: more asserts
520 assertThrows(RestconfDocumentedException.class,
521 () -> RestconfDataServiceImpl.validTopLevelNodeName(GAP_IID.getAncestor(1), payload));
525 public void testValidateListKeysEqualityInPayloadAndUri() {
526 final var iidContext = InstanceIdentifierContext.ofLocalPath(JUKEBOX_SCHEMA, YangInstanceIdentifier.builder()
528 .node(PLAYLIST_QNAME)
529 .nodeWithKey(PLAYLIST_QNAME, NAME_QNAME, "name of band")
531 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, BAND_ENTRY);
532 RestconfDataServiceImpl.validateListKeysEqualityInPayloadAndUri(payload);