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.doCallRealMethod;
17 import static org.mockito.Mockito.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.opendaylight.restconf.common.patch.PatchEditOperation.CREATE;
20 import static org.opendaylight.restconf.common.patch.PatchEditOperation.DELETE;
21 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REMOVE;
22 import static org.opendaylight.restconf.common.patch.PatchEditOperation.REPLACE;
23 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
24 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
25 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Optional;
33 import javax.ws.rs.core.MultivaluedHashMap;
34 import javax.ws.rs.core.MultivaluedMap;
35 import javax.ws.rs.core.Response;
36 import javax.ws.rs.core.UriBuilder;
37 import javax.ws.rs.core.UriInfo;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.mockito.Mock;
41 import org.mockito.Mockito;
42 import org.mockito.MockitoAnnotations;
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.netconf.dom.api.NetconfDataTreeService;
55 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
56 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
57 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
58 import org.opendaylight.restconf.common.patch.PatchContext;
59 import org.opendaylight.restconf.common.patch.PatchEntity;
60 import org.opendaylight.restconf.common.patch.PatchStatusContext;
61 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
62 import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
63 import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
64 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
65 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
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.Configuration;
71 import org.opendaylight.yangtools.yang.common.QName;
72 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
73 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
74 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
75 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
76 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
77 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
78 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
79 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
80 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
81 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
82 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
83 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
84 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
85 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
86 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
87 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
88 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
89 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
91 public class RestconfDataServiceImplTest {
93 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
95 private ContainerNode buildBaseCont;
96 private ContainerNode buildBaseContConfig;
97 private ContainerNode buildBaseContOperational;
98 private EffectiveModelContext contextRef;
99 private YangInstanceIdentifier iidBase;
100 private DataSchemaNode schemaNode;
101 private RestconfDataServiceImpl dataService;
102 private QName baseQName;
103 private QName containerPlayerQname;
104 private QName leafQname;
105 private ContainerNode buildPlayerCont;
106 private ContainerNode buildLibraryCont;
107 private MapNode buildPlaylistList;
108 private TransactionChainHandler transactionChainHandler;
111 private DOMTransactionChain domTransactionChain;
113 private UriInfo uriInfo;
115 private DOMDataTreeReadWriteTransaction readWrite;
117 private DOMDataTreeReadTransaction read;
119 private DOMDataTreeWriteTransaction write;
121 private DOMMountPointService mountPointService;
123 private DOMMountPoint mountPoint;
125 private DOMDataBroker mountDataBroker;
127 private NetconfDataTreeService netconfService;
129 private ActionServiceHandler actionServiceHandler;
131 private DOMTransactionChain mountTransactionChain;
133 private RestconfStreamsSubscriptionService delegRestconfSubscrService;
135 private Configuration configuration;
138 public void setUp() throws Exception {
139 MockitoAnnotations.initMocks(this);
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).getChild(this.iidBase).getDataSchemaNode();
197 doReturn(CommitInfo.emptyFluentFuture()).when(this.write).commit();
198 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
200 doReturn(this.read).when(domTransactionChain).newReadOnlyTransaction();
201 doReturn(this.readWrite).when(domTransactionChain).newReadWriteTransaction();
202 doReturn(this.write).when(domTransactionChain).newWriteOnlyTransaction();
204 DOMDataBroker mockDataBroker = Mockito.mock(DOMDataBroker.class);
205 Mockito.doReturn(domTransactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
207 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
209 final SchemaContextHandler schemaContextHandler = new SchemaContextHandler(transactionChainHandler,
210 Mockito.mock(DOMSchemaService.class));
212 schemaContextHandler.onModelContextUpdated(this.contextRef);
213 this.dataService = new RestconfDataServiceImpl(schemaContextHandler, this.transactionChainHandler,
214 new DOMMountPointServiceHandler(mountPointService), this.delegRestconfSubscrService,
215 this.actionServiceHandler, configuration);
216 doReturn(Optional.of(this.mountPoint)).when(this.mountPointService)
217 .getMountPoint(any(YangInstanceIdentifier.class));
218 doCallRealMethod().when(this.mountPoint).getSchemaContext();
219 doReturn(this.contextRef).when(this.mountPoint).getEffectiveModelContext();
220 doReturn(Optional.of(this.mountDataBroker)).when(this.mountPoint).getService(DOMDataBroker.class);
221 doReturn(this.mountTransactionChain).when(this.mountDataBroker)
222 .createTransactionChain(any(DOMTransactionChainListener.class));
223 doReturn(this.read).when(this.mountTransactionChain).newReadOnlyTransaction();
224 doReturn(this.readWrite).when(this.mountTransactionChain).newReadWriteTransaction();
228 public void testReadData() {
229 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
230 doReturn(immediateFluentFuture(Optional.of(this.buildBaseCont))).when(this.read)
231 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
232 doReturn(immediateFluentFuture(Optional.empty()))
233 .when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
234 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
235 assertNotNull(response);
236 assertEquals(200, response.getStatus());
237 assertEquals(this.buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
241 public void testReadRootData() {
242 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
243 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContConfig))))
245 .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.empty());
246 doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContOperational))))
248 .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.empty());
249 final Response response = this.dataService.readData(this.uriInfo);
250 assertNotNull(response);
251 assertEquals(200, response.getStatus());
253 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
254 assertTrue(data instanceof ContainerNode);
255 final Collection<DataContainerChild<? extends PathArgument, ?>> rootNodes = ((ContainerNode) data).getValue();
256 assertEquals(1, rootNodes.size());
257 final Collection<DataContainerChild<? extends PathArgument, ?>> allDataChildren
258 = ((ContainerNode) rootNodes.iterator().next()).getValue();
259 assertEquals(3, allDataChildren.size());
262 private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild<?, ?> data) {
263 return ImmutableContainerNodeBuilder.create()
264 .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
270 * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
271 * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
274 public void testReadDataMountPoint() {
275 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
276 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
277 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
278 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
279 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
281 final Response response = this.dataService.readData(
282 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", this.uriInfo);
284 assertNotNull(response);
285 assertEquals(200, response.getStatus());
287 // response must contain all child nodes from config and operational containers merged in one container
288 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
289 assertTrue(data instanceof ContainerNode);
290 assertEquals(3, ((ContainerNode) data).getValue().size());
291 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
292 assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
293 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
296 @Test(expected = RestconfDocumentedException.class)
297 public void testReadDataNoData() {
298 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
299 doReturn(immediateFluentFuture(Optional.empty()))
300 .when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
301 doReturn(immediateFluentFuture(Optional.empty()))
302 .when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
303 this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
307 * Read data from config datastore according to content parameter.
310 public void testReadDataConfigTest() {
311 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
312 parameters.put("content", Collections.singletonList("config"));
314 doReturn(parameters).when(this.uriInfo).getQueryParameters();
315 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
316 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
317 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
318 .read(LogicalDatastoreType.OPERATIONAL, 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.buildBaseContConfig))).when(this.read)
346 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
347 doReturn(immediateFluentFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
348 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
350 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
352 assertNotNull(response);
353 assertEquals(200, response.getStatus());
355 // response must contain only operational data
356 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
358 // state data present
359 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
360 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
362 // config data absent
363 assertFalse(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
367 public void testPutData() {
368 final InstanceIdentifierContext<DataSchemaNode> iidContext =
369 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
370 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
372 doReturn(immediateTrueFluentFuture()).when(this.readWrite)
373 .exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
374 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
375 final Response response = this.dataService.putData(null, payload, this.uriInfo);
376 assertNotNull(response);
377 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
381 public void testPutDataWithMountPoint() {
382 // final DOMDataBroker dataBroker = Mockito.mock(DOMDataBroker.class);
383 // doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
384 // doReturn(this.transactionChainHandler.get()).when(dataBroker)
385 // .createTransactionChain(RestConnectorProvider.TRANSACTION_CHAIN_LISTENER);
386 final InstanceIdentifierContext<DataSchemaNode> iidContext =
387 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, mountPoint, this.contextRef);
388 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
390 doReturn(immediateTrueFluentFuture()).when(this.readWrite)
391 .exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
392 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
393 final Response response = this.dataService.putData(null, payload, this.uriInfo);
394 assertNotNull(response);
395 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
399 public void testPostData() {
400 final QName listQname = QName.create(this.baseQName, "playlist");
401 final QName listKeyQname = QName.create(this.baseQName, "name");
402 final NodeIdentifierWithPredicates nodeWithKey =
403 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band");
404 final LeafNode<Object> content = Builders.leafBuilder()
405 .withNodeIdentifier(new NodeIdentifier(QName.create(this.baseQName, "name")))
406 .withValue("name of band")
408 final LeafNode<Object> content2 = Builders.leafBuilder()
409 .withNodeIdentifier(new NodeIdentifier(QName.create(this.baseQName, "description")))
410 .withValue("band description")
412 final MapEntryNode mapEntryNode = Builders.mapEntryBuilder()
413 .withNodeIdentifier(nodeWithKey)
417 final MapNode buildList = Builders.mapBuilder()
418 .withNodeIdentifier(new NodeIdentifier(listQname))
419 .withChild(mapEntryNode)
422 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
423 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
424 new InstanceIdentifierContext<>(this.iidBase, null, null, this.contextRef);
425 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, buildList);
426 doReturn(immediateFluentFuture(Optional.empty()))
427 .when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
428 final MapNode data = (MapNode) payload.getData();
429 final NodeIdentifierWithPredicates identifier =
430 data.getValue().iterator().next().getIdentifier();
431 final YangInstanceIdentifier node =
432 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
433 doReturn(immediateFalseFluentFuture())
434 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
435 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
436 doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/15/")).when(this.uriInfo).getBaseUriBuilder();
438 final Response response = this.dataService.postData(null, payload, this.uriInfo);
439 assertEquals(201, response.getStatus());
443 public void testDeleteData() {
444 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
445 doReturn(immediateTrueFluentFuture())
446 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
447 final Response response = this.dataService.deleteData("example-jukebox:jukebox");
448 assertNotNull(response);
449 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
453 * Test of deleting data on mount point.
456 public void testDeleteDataMountPoint() {
457 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
458 doReturn(immediateTrueFluentFuture())
459 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
460 final Response response =
461 this.dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
462 assertNotNull(response);
463 assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
467 public void testPatchData() throws Exception {
468 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
469 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
470 final List<PatchEntity> entity = new ArrayList<>();
471 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
472 .node(this.containerPlayerQname)
473 .node(this.leafQname)
475 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
476 entity.add(new PatchEntity("replace data", REPLACE, this.iidBase, this.buildBaseCont));
477 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
478 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
480 doReturn(immediateFluentFuture(Optional.of(this.buildBaseCont))).when(this.read)
481 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
482 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
483 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
484 doReturn(immediateFalseFluentFuture())
485 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
486 doReturn(immediateTrueFluentFuture())
487 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
488 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
489 assertTrue(status.isOk());
490 assertEquals(3, status.getEditCollection().size());
491 assertEquals("replace data", status.getEditCollection().get(1).getEditId());
495 public void testPatchDataMountPoint() throws Exception {
496 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
497 this.iidBase, this.schemaNode, this.mountPoint, this.contextRef);
498 final List<PatchEntity> entity = new ArrayList<>();
499 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
500 .node(this.containerPlayerQname)
501 .node(this.leafQname)
503 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
504 entity.add(new PatchEntity("replace data", REPLACE, this.iidBase, this.buildBaseCont));
505 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
506 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
508 doReturn(immediateFluentFuture(Optional.of(this.buildBaseCont))).when(this.read)
509 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
510 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
511 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
512 doReturn(immediateFalseFluentFuture())
513 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
514 doReturn(immediateTrueFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
516 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
517 assertTrue(status.isOk());
518 assertEquals(3, status.getEditCollection().size());
519 assertNull(status.getGlobalErrors());
523 public void testPatchDataDeleteNotExist() throws Exception {
524 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
525 new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef);
526 final List<PatchEntity> entity = new ArrayList<>();
527 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
528 .node(this.containerPlayerQname)
529 .node(this.leafQname)
531 entity.add(new PatchEntity("create data", CREATE, this.iidBase, this.buildBaseCont));
532 entity.add(new PatchEntity("remove data", REMOVE, iidleaf));
533 entity.add(new PatchEntity("delete data", DELETE, iidleaf));
534 final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
536 doReturn(immediateFluentFuture(Optional.of(this.buildBaseCont))).when(this.read)
537 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
538 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
539 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
540 doReturn(immediateFalseFluentFuture())
541 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
542 doReturn(immediateFalseFluentFuture())
543 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
544 doReturn(true).when(this.readWrite).cancel();
545 final PatchStatusContext status = this.dataService.patchData(patch, this.uriInfo);
547 assertFalse(status.isOk());
548 assertEquals(3, status.getEditCollection().size());
549 assertTrue(status.getEditCollection().get(0).isOk());
550 assertTrue(status.getEditCollection().get(1).isOk());
551 assertFalse(status.getEditCollection().get(2).isOk());
552 assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
553 final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
554 assertEquals("Data does not exist", errorMessage);
558 public void testGetRestconfStrategy() {
559 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
560 this.iidBase, this.schemaNode, this.mountPoint, this.contextRef);
562 RestconfStrategy restconfStrategy = this.dataService.getRestconfStrategy(this.mountPoint);
563 assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
565 doReturn(Optional.of(this.netconfService)).when(this.mountPoint).getService(NetconfDataTreeService.class);
566 restconfStrategy = this.dataService.getRestconfStrategy(this.mountPoint);
567 assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);