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.assertTrue;
15 import static org.mockito.ArgumentMatchers.any;
16 import static org.mockito.Mockito.doNothing;
17 import static org.mockito.Mockito.doReturn;
18 import static org.opendaylight.restconf.common.patch.PatchEditOperation.CREATE;
19 import static org.opendaylight.restconf.common.patch.PatchEditOperation.DELETE;
20 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REMOVE;
21 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REPLACE;
22 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
23 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
24 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Optional;
32 import javax.ws.rs.core.MultivaluedHashMap;
33 import javax.ws.rs.core.MultivaluedMap;
34 import javax.ws.rs.core.Response;
35 import javax.ws.rs.core.UriBuilder;
36 import javax.ws.rs.core.UriInfo;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.mockito.Mock;
41 import org.mockito.Mockito;
42 import org.mockito.junit.MockitoJUnitRunner;
43 import org.opendaylight.mdsal.common.api.CommitInfo;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
46 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
47 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
48 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
49 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
50 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
51 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
52 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
53 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
54 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
55 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
56 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
57 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
58 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
59 import org.opendaylight.restconf.common.patch.PatchContext;
60 import org.opendaylight.restconf.common.patch.PatchEntity;
61 import org.opendaylight.restconf.common.patch.PatchStatusContext;
62 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
63 import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
64 import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
65 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
66 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
67 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
68 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
69 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
70 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
71 import org.opendaylight.restconf.nb.rfc8040.streams.Configuration;
72 import org.opendaylight.yangtools.yang.common.QName;
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.YangInstanceIdentifier.NodeIdentifierWithPredicates;
76 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
77 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
78 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
79 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
80 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
81 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
82 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
83 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
84 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
85 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
86 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
87 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
88 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
89 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
90 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
92 @RunWith(MockitoJUnitRunner.StrictStubs.class)
93 public class RestconfDataServiceImplTest {
95 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
97 private ContainerNode buildBaseCont;
98 private ContainerNode buildBaseContConfig;
99 private ContainerNode buildBaseContOperational;
100 private EffectiveModelContext contextRef;
101 private YangInstanceIdentifier iidBase;
102 private DataSchemaNode schemaNode;
103 private RestconfDataServiceImpl dataService;
104 private QName baseQName;
105 private QName containerPlayerQname;
106 private QName leafQname;
107 private ContainerNode buildPlayerCont;
108 private ContainerNode buildLibraryCont;
109 private MapNode buildPlaylistList;
110 private TransactionChainHandler transactionChainHandler;
113 private DOMTransactionChain domTransactionChain;
115 private UriInfo uriInfo;
117 private DOMDataTreeReadWriteTransaction readWrite;
119 private DOMDataTreeReadTransaction read;
121 private DOMDataTreeWriteTransaction write;
123 private DOMMountPointService mountPointService;
125 private DOMMountPoint mountPoint;
127 private DOMDataBroker mountDataBroker;
129 private NetconfDataTreeService netconfService;
131 private ActionServiceHandler actionServiceHandler;
133 private DOMTransactionChain mountTransactionChain;
135 private RestconfStreamsSubscriptionService delegRestconfSubscrService;
137 private Configuration configuration;
140 public void setUp() throws Exception {
141 final MultivaluedMap<String, String> value = Mockito.mock(MultivaluedMap.class);
142 Mockito.when(value.entrySet()).thenReturn(new HashSet<>());
143 Mockito.when(this.uriInfo.getQueryParameters()).thenReturn(value);
145 this.baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
146 this.containerPlayerQname = QName.create(this.baseQName, "player");
147 this.leafQname = QName.create(this.baseQName, "gap");
149 final QName containerLibraryQName = QName.create(this.baseQName, "library");
150 final QName listPlaylistQName = QName.create(this.baseQName, "playlist");
152 final LeafNode<?> buildLeaf = Builders.leafBuilder()
153 .withNodeIdentifier(new NodeIdentifier(this.leafQname))
157 this.buildPlayerCont = Builders.containerBuilder()
158 .withNodeIdentifier(new NodeIdentifier(this.containerPlayerQname))
159 .withChild(buildLeaf)
162 this.buildLibraryCont = Builders.containerBuilder()
163 .withNodeIdentifier(new NodeIdentifier(containerLibraryQName))
166 this.buildPlaylistList = Builders.mapBuilder()
167 .withNodeIdentifier(new NodeIdentifier(listPlaylistQName))
170 this.buildBaseCont = Builders.containerBuilder()
171 .withNodeIdentifier(new NodeIdentifier(this.baseQName))
172 .withChild(this.buildPlayerCont)
175 // config contains one child the same as in operational and one additional
176 this.buildBaseContConfig = Builders.containerBuilder()
177 .withNodeIdentifier(new NodeIdentifier(this.baseQName))
178 .withChild(this.buildPlayerCont)
179 .withChild(this.buildLibraryCont)
182 // operational contains one child the same as in config and one additional
183 this.buildBaseContOperational = Builders.containerBuilder()
184 .withNodeIdentifier(new NodeIdentifier(this.baseQName))
185 .withChild(this.buildPlayerCont)
186 .withChild(this.buildPlaylistList)
189 this.iidBase = YangInstanceIdentifier.builder()
190 .node(this.baseQName)
194 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
195 this.schemaNode = DataSchemaContextTree.from(this.contextRef).findChild(this.iidBase).orElseThrow(
196 ).getDataSchemaNode();
198 doReturn(CommitInfo.emptyFluentFuture()).when(this.write).commit();
199 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
201 doReturn(this.read).when(domTransactionChain).newReadOnlyTransaction();
202 doReturn(this.readWrite).when(domTransactionChain).newReadWriteTransaction();
203 doReturn(this.write).when(domTransactionChain).newWriteOnlyTransaction();
205 DOMDataBroker mockDataBroker = Mockito.mock(DOMDataBroker.class);
206 Mockito.doReturn(domTransactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
208 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
210 final SchemaContextHandler schemaContextHandler = new SchemaContextHandler(transactionChainHandler,
211 Mockito.mock(DOMSchemaService.class));
213 schemaContextHandler.onModelContextUpdated(this.contextRef);
214 this.dataService = new RestconfDataServiceImpl(schemaContextHandler, this.transactionChainHandler,
215 new DOMMountPointServiceHandler(mountPointService), this.delegRestconfSubscrService,
216 this.actionServiceHandler, configuration);
217 doReturn(Optional.of(this.mountPoint)).when(this.mountPointService)
218 .getMountPoint(any(YangInstanceIdentifier.class));
219 doReturn(Optional.of(FixedDOMSchemaService.of(this.contextRef))).when(this.mountPoint)
220 .getService(DOMSchemaService.class);
221 doReturn(Optional.of(this.mountDataBroker)).when(this.mountPoint).getService(DOMDataBroker.class);
222 doReturn(Optional.empty()).when(this.mountPoint).getService(NetconfDataTreeService.class);
223 doReturn(this.mountTransactionChain).when(this.mountDataBroker)
224 .createTransactionChain(any(DOMTransactionChainListener.class));
225 doReturn(this.read).when(this.mountTransactionChain).newReadOnlyTransaction();
226 doReturn(this.readWrite).when(this.mountTransactionChain).newReadWriteTransaction();
230 public void testReadData() {
231 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
232 doReturn(immediateFluentFuture(Optional.of(this.buildBaseCont))).when(this.read)
233 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
234 doReturn(immediateFluentFuture(Optional.empty()))
235 .when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
236 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
237 assertNotNull(response);
238 assertEquals(200, response.getStatus());
239 assertEquals(this.buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
243 public void testReadRootData() {
244 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
245 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContConfig))))
247 .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.empty());
248 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContOperational))))
250 .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.empty());
251 final Response response = this.dataService.readData(this.uriInfo);
252 assertNotNull(response);
253 assertEquals(200, response.getStatus());
255 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
256 assertTrue(data instanceof ContainerNode);
257 final Collection<DataContainerChild<? extends PathArgument, ?>> rootNodes = ((ContainerNode) data).getValue();
258 assertEquals(1, rootNodes.size());
259 final Collection<DataContainerChild<? extends PathArgument, ?>> allDataChildren
260 = ((ContainerNode) rootNodes.iterator().next()).getValue();
261 assertEquals(3, allDataChildren.size());
264 private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild<?, ?> data) {
265 return ImmutableContainerNodeBuilder.create()
266 .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
272 * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
273 * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
276 public void testReadDataMountPoint() {
277 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
278 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
279 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
280 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
281 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
283 final Response response = this.dataService.readData(
284 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", this.uriInfo);
286 assertNotNull(response);
287 assertEquals(200, response.getStatus());
289 // response must contain all child nodes from config and operational containers merged in one container
290 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
291 assertTrue(data instanceof ContainerNode);
292 assertEquals(3, ((ContainerNode) data).getValue().size());
293 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
294 assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
295 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
298 @Test(expected = RestconfDocumentedException.class)
299 public void testReadDataNoData() {
300 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
301 doReturn(immediateFluentFuture(Optional.empty()))
302 .when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
303 doReturn(immediateFluentFuture(Optional.empty()))
304 .when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
305 this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
309 * Read data from config datastore according to content parameter.
312 public void testReadDataConfigTest() {
313 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
314 parameters.put("content", Collections.singletonList("config"));
316 doReturn(parameters).when(this.uriInfo).getQueryParameters();
317 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
318 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
320 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
322 assertNotNull(response);
323 assertEquals(200, response.getStatus());
325 // response must contain only config data
326 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
328 // config data present
329 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
330 assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
333 assertFalse(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
337 * Read data from operational datastore according to content parameter.
340 public void testReadDataOperationalTest() {
341 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
342 parameters.put("content", Collections.singletonList("nonconfig"));
344 doReturn(parameters).when(this.uriInfo).getQueryParameters();
345 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
346 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
348 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
350 assertNotNull(response);
351 assertEquals(200, response.getStatus());
353 // response must contain only operational data
354 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
356 // state data present
357 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
358 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
360 // config data absent
361 assertFalse(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
365 public void testPutData() {
366 final InstanceIdentifierContext<DataSchemaNode> iidContext =
367 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
368 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
370 doReturn(immediateTrueFluentFuture()).when(this.read)
371 .exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
372 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
373 final Response response = this.dataService.putData(null, payload, this.uriInfo);
374 assertNotNull(response);
375 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
379 public void testPutDataWithMountPoint() {
380 // final DOMDataBroker dataBroker = Mockito.mock(DOMDataBroker.class);
381 // doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
382 // doReturn(this.transactionChainHandler.get()).when(dataBroker)
383 // .createTransactionChain(RestConnectorProvider.TRANSACTION_CHAIN_LISTENER);
384 final InstanceIdentifierContext<DataSchemaNode> iidContext =
385 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, mountPoint, this.contextRef);
386 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
388 doReturn(immediateTrueFluentFuture()).when(this.read)
389 .exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
390 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
391 final Response response = this.dataService.putData(null, payload, this.uriInfo);
392 assertNotNull(response);
393 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
397 public void testPostData() {
398 final QName listQname = QName.create(this.baseQName, "playlist");
399 final QName listKeyQname = QName.create(this.baseQName, "name");
400 final NodeIdentifierWithPredicates nodeWithKey =
401 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band");
402 final LeafNode<Object> content = Builders.leafBuilder()
403 .withNodeIdentifier(new NodeIdentifier(QName.create(this.baseQName, "name")))
404 .withValue("name of band")
406 final LeafNode<Object> content2 = Builders.leafBuilder()
407 .withNodeIdentifier(new NodeIdentifier(QName.create(this.baseQName, "description")))
408 .withValue("band description")
410 final MapEntryNode mapEntryNode = Builders.mapEntryBuilder()
411 .withNodeIdentifier(nodeWithKey)
415 final MapNode buildList = Builders.mapBuilder()
416 .withNodeIdentifier(new NodeIdentifier(listQname))
417 .withChild(mapEntryNode)
420 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
421 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
422 new InstanceIdentifierContext<>(this.iidBase, null, null, this.contextRef);
423 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, buildList);
424 final MapNode data = (MapNode) payload.getData();
425 final MapEntryNode entryNode = data.getValue().iterator().next();
426 final NodeIdentifierWithPredicates identifier = entryNode.getIdentifier();
427 final YangInstanceIdentifier node =
428 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
429 doReturn(immediateFalseFluentFuture())
430 .when(this.read).exists(LogicalDatastoreType.CONFIGURATION, node);
431 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
432 doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/15/")).when(this.uriInfo).getBaseUriBuilder();
434 final Response response = this.dataService.postData(null, payload, this.uriInfo);
435 assertEquals(201, response.getStatus());
439 public void testDeleteData() {
440 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
441 doReturn(immediateTrueFluentFuture())
442 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
443 final Response response = this.dataService.deleteData("example-jukebox:jukebox");
444 assertNotNull(response);
445 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
449 * Test of deleting data on mount point.
452 public void testDeleteDataMountPoint() {
453 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
454 doReturn(immediateTrueFluentFuture())
455 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
456 final Response response =
457 this.dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
458 assertNotNull(response);
459 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
463 public void testPatchData() {
464 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
465 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
466 final List<PatchEntity> entity = new ArrayList<>();
467 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
468 .node(this.containerPlayerQname)
469 .node(this.leafQname)
471 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
472 entity.add(new PatchEntity("replace data", REPLACE, this.iidBase, this.buildBaseCont));
473 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
474 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
476 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
477 doReturn(immediateFalseFluentFuture())
478 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
479 doReturn(immediateTrueFluentFuture())
480 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
481 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
482 assertTrue(status.isOk());
483 assertEquals(3, status.getEditCollection().size());
484 assertEquals("replace data", status.getEditCollection().get(1).getEditId());
488 public void testPatchDataMountPoint() throws Exception {
489 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
490 this.iidBase, this.schemaNode, this.mountPoint, this.contextRef);
491 final List<PatchEntity> entity = new ArrayList<>();
492 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
493 .node(this.containerPlayerQname)
494 .node(this.leafQname)
496 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
497 entity.add(new PatchEntity("replace data", REPLACE, this.iidBase, this.buildBaseCont));
498 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
499 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
501 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
502 doReturn(immediateFalseFluentFuture())
503 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
504 doReturn(immediateTrueFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
506 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
507 assertTrue(status.isOk());
508 assertEquals(3, status.getEditCollection().size());
509 assertNull(status.getGlobalErrors());
513 public void testPatchDataDeleteNotExist() {
514 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
515 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
516 final List<PatchEntity> entity = new ArrayList<>();
517 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
518 .node(this.containerPlayerQname)
519 .node(this.leafQname)
521 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
522 entity.add(new PatchEntity("remove data", REMOVE, iidleaf));
523 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
524 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
526 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
527 doReturn(immediateFalseFluentFuture())
528 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
529 doReturn(immediateFalseFluentFuture())
530 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
531 doReturn(true).when(this.readWrite).cancel();
532 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
534 assertFalse(status.isOk());
535 assertEquals(3, status.getEditCollection().size());
536 assertTrue(status.getEditCollection().get(0).isOk());
537 assertTrue(status.getEditCollection().get(1).isOk());
538 assertFalse(status.getEditCollection().get(2).isOk());
539 assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
540 final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
541 assertEquals("Data does not exist", errorMessage);
545 public void testGetRestconfStrategy() {
546 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
547 this.iidBase, this.schemaNode, this.mountPoint, this.contextRef);
549 RestconfStrategy restconfStrategy = this.dataService.getRestconfStrategy(this.mountPoint);
550 assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
552 doReturn(Optional.of(this.netconfService)).when(this.mountPoint).getService(NetconfDataTreeService.class);
553 restconfStrategy = this.dataService.getRestconfStrategy(this.mountPoint);
554 assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);