Reduce exception guard
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / services / impl / RestconfDataServiceImplTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
9
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;
27
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.List;
31 import java.util.Optional;
32 import java.util.Set;
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.junit.runner.RunWith;
41 import org.mockito.Mock;
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.DOMActionService;
46 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
47 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
48 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
49 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
50 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
51 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
52 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
53 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
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.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.SchemaContextHandler;
63 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
64 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
65 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
66 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
67 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
68 import org.opendaylight.restconf.nb.rfc8040.streams.Configuration;
69 import org.opendaylight.yangtools.yang.common.ErrorTag;
70 import org.opendaylight.yangtools.yang.common.ErrorType;
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.schema.ContainerNode;
76 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
77 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
78 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
79 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
80 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
81 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
82 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
83 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
84 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
85 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
86 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
87
88 @RunWith(MockitoJUnitRunner.StrictStubs.class)
89 public class RestconfDataServiceImplTest {
90
91     private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
92
93     private ContainerNode buildBaseCont;
94     private ContainerNode buildBaseContConfig;
95     private ContainerNode buildBaseContOperational;
96     private EffectiveModelContext contextRef;
97     private YangInstanceIdentifier iidBase;
98     private RestconfDataServiceImpl dataService;
99     private QName baseQName;
100     private QName containerPlayerQname;
101     private QName leafQname;
102     private ContainerNode buildPlayerCont;
103     private ContainerNode buildLibraryCont;
104     private MapNode buildPlaylistList;
105
106     @Mock
107     private DOMTransactionChain domTransactionChain;
108     @Mock
109     private UriInfo uriInfo;
110     @Mock
111     private DOMDataTreeReadWriteTransaction readWrite;
112     @Mock
113     private DOMDataTreeReadTransaction read;
114     @Mock
115     private DOMDataTreeWriteTransaction write;
116     @Mock
117     private DOMMountPointService mountPointService;
118     @Mock
119     private DOMMountPoint mountPoint;
120     @Mock
121     private DOMDataBroker mountDataBroker;
122     @Mock
123     private NetconfDataTreeService netconfService;
124     @Mock
125     private DOMActionService actionService;
126     @Mock
127     private RestconfStreamsSubscriptionService delegRestconfSubscrService;
128     @Mock
129     private Configuration configuration;
130     @Mock
131     private MultivaluedMap<String, String> queryParamenters;
132
133     @Before
134     public void setUp() throws Exception {
135         doReturn(Set.of()).when(queryParamenters).entrySet();
136         doReturn(queryParamenters).when(uriInfo).getQueryParameters();
137
138         baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
139         containerPlayerQname = QName.create(baseQName, "player");
140         leafQname = QName.create(baseQName, "gap");
141
142         final QName containerLibraryQName = QName.create(baseQName, "library");
143         final QName listPlaylistQName = QName.create(baseQName, "playlist");
144
145         final LeafNode<?> buildLeaf = Builders.leafBuilder()
146                 .withNodeIdentifier(new NodeIdentifier(leafQname))
147                 .withValue(0.2)
148                 .build();
149
150         buildPlayerCont = Builders.containerBuilder()
151                 .withNodeIdentifier(new NodeIdentifier(containerPlayerQname))
152                 .withChild(buildLeaf)
153                 .build();
154
155         buildLibraryCont = Builders.containerBuilder()
156                 .withNodeIdentifier(new NodeIdentifier(containerLibraryQName))
157                 .build();
158
159         buildPlaylistList = Builders.mapBuilder()
160                 .withNodeIdentifier(new NodeIdentifier(listPlaylistQName))
161                 .build();
162
163         buildBaseCont = Builders.containerBuilder()
164                 .withNodeIdentifier(new NodeIdentifier(baseQName))
165                 .withChild(buildPlayerCont)
166                 .build();
167
168         // config contains one child the same as in operational and one additional
169         buildBaseContConfig = Builders.containerBuilder()
170                 .withNodeIdentifier(new NodeIdentifier(baseQName))
171                 .withChild(buildPlayerCont)
172                 .withChild(buildLibraryCont)
173                 .build();
174
175         // operational contains one child the same as in config and one additional
176         buildBaseContOperational = Builders.containerBuilder()
177                 .withNodeIdentifier(new NodeIdentifier(baseQName))
178                 .withChild(buildPlayerCont)
179                 .withChild(buildPlaylistList)
180                 .build();
181
182         iidBase = YangInstanceIdentifier.builder()
183                 .node(baseQName)
184                 .build();
185
186         contextRef =
187                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
188
189         doReturn(CommitInfo.emptyFluentFuture()).when(write).commit();
190         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
191
192         DOMDataBroker mockDataBroker = mock(DOMDataBroker.class);
193         doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
194         doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
195         doReturn(write).when(mockDataBroker).newWriteOnlyTransaction();
196
197         final SchemaContextHandler schemaContextHandler = new SchemaContextHandler(
198                 mockDataBroker, mock(DOMSchemaService.class));
199
200         schemaContextHandler.onModelContextUpdated(contextRef);
201         dataService = new RestconfDataServiceImpl(schemaContextHandler, mockDataBroker, mountPointService,
202                 delegRestconfSubscrService, actionService, configuration);
203         doReturn(Optional.of(mountPoint)).when(mountPointService)
204                 .getMountPoint(any(YangInstanceIdentifier.class));
205         doReturn(Optional.of(FixedDOMSchemaService.of(contextRef))).when(mountPoint)
206                 .getService(DOMSchemaService.class);
207         doReturn(Optional.of(mountDataBroker)).when(mountPoint).getService(DOMDataBroker.class);
208         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
209         doReturn(read).when(mountDataBroker).newReadOnlyTransaction();
210         doReturn(readWrite).when(mountDataBroker).newReadWriteTransaction();
211     }
212
213     @Test
214     public void testReadData() {
215         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
216         doReturn(immediateFluentFuture(Optional.of(buildBaseCont))).when(read)
217                 .read(LogicalDatastoreType.CONFIGURATION, iidBase);
218         doReturn(immediateFluentFuture(Optional.empty()))
219                 .when(read).read(LogicalDatastoreType.OPERATIONAL, iidBase);
220         final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
221         assertNotNull(response);
222         assertEquals(200, response.getStatus());
223         assertEquals(buildBaseCont, ((NormalizedNodePayload) response.getEntity()).getData());
224     }
225
226     @Test
227     public void testReadRootData() {
228         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
229         doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContConfig))))
230                 .when(read)
231                 .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.empty());
232         doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(buildBaseContOperational))))
233                 .when(read)
234                 .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.empty());
235         final Response response = dataService.readData(uriInfo);
236         assertNotNull(response);
237         assertEquals(200, response.getStatus());
238
239         final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
240         assertTrue(data instanceof ContainerNode);
241         final Collection<DataContainerChild> rootNodes = ((ContainerNode) data).body();
242         assertEquals(1, rootNodes.size());
243         final Collection<DataContainerChild> allDataChildren = ((ContainerNode) rootNodes.iterator().next()).body();
244         assertEquals(3, allDataChildren.size());
245     }
246
247     private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild data) {
248         return ImmutableContainerNodeBuilder.create()
249                 .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
250                 .withChild(data)
251                 .build();
252     }
253
254     /**
255      * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
256      * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
257      */
258     @Test
259     public void testReadDataMountPoint() {
260         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
261         doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
262                 .read(LogicalDatastoreType.CONFIGURATION, iidBase);
263         doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
264                 .read(LogicalDatastoreType.OPERATIONAL, iidBase);
265
266         final Response response = dataService.readData(
267                 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", uriInfo);
268
269         assertNotNull(response);
270         assertEquals(200, response.getStatus());
271
272         // response must contain all child nodes from config and operational containers merged in one container
273         final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
274         assertTrue(data instanceof ContainerNode);
275         assertEquals(3, ((ContainerNode) data).size());
276         assertTrue(((ContainerNode) data).findChildByArg(buildPlayerCont.getIdentifier()).isPresent());
277         assertTrue(((ContainerNode) data).findChildByArg(buildLibraryCont.getIdentifier()).isPresent());
278         assertTrue(((ContainerNode) data).findChildByArg(buildPlaylistList.getIdentifier()).isPresent());
279     }
280
281     @Test
282     public void testReadDataNoData() {
283         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
284         doReturn(immediateFluentFuture(Optional.empty()))
285                 .when(read).read(LogicalDatastoreType.CONFIGURATION, iidBase);
286         doReturn(immediateFluentFuture(Optional.empty()))
287                 .when(read).read(LogicalDatastoreType.OPERATIONAL, iidBase);
288
289         final var errors = assertThrows(RestconfDocumentedException.class,
290             () -> dataService.readData("example-jukebox:jukebox", uriInfo)).getErrors();
291         assertEquals(1, errors.size());
292         final var error = errors.get(0);
293         assertEquals(ErrorType.PROTOCOL, error.getErrorType());
294         assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
295         assertEquals("Request could not be completed because the relevant data model content does not exist",
296             error.getErrorMessage());
297     }
298
299     /**
300      * Read data from config datastore according to content parameter.
301      */
302     @Test
303     public void testReadDataConfigTest() {
304         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
305         parameters.put("content", List.of("config"));
306
307         doReturn(parameters).when(uriInfo).getQueryParameters();
308         doReturn(immediateFluentFuture(Optional.of(buildBaseContConfig))).when(read)
309                 .read(LogicalDatastoreType.CONFIGURATION, iidBase);
310
311         final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
312
313         assertNotNull(response);
314         assertEquals(200, response.getStatus());
315
316         // response must contain only config data
317         final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
318
319         // config data present
320         assertTrue(((ContainerNode) data).findChildByArg(buildPlayerCont.getIdentifier()).isPresent());
321         assertTrue(((ContainerNode) data).findChildByArg(buildLibraryCont.getIdentifier()).isPresent());
322
323         // state data absent
324         assertFalse(((ContainerNode) data).findChildByArg(buildPlaylistList.getIdentifier()).isPresent());
325     }
326
327     /**
328      * Read data from operational datastore according to content parameter.
329      */
330     @Test
331     public void testReadDataOperationalTest() {
332         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
333         parameters.put("content", List.of("nonconfig"));
334
335         doReturn(parameters).when(uriInfo).getQueryParameters();
336         doReturn(immediateFluentFuture(Optional.of(buildBaseContOperational))).when(read)
337                 .read(LogicalDatastoreType.OPERATIONAL, iidBase);
338
339         final Response response = dataService.readData("example-jukebox:jukebox", uriInfo);
340
341         assertNotNull(response);
342         assertEquals(200, response.getStatus());
343
344         // response must contain only operational data
345         final NormalizedNode data = ((NormalizedNodePayload) response.getEntity()).getData();
346
347         // state data present
348         assertTrue(((ContainerNode) data).findChildByArg(buildPlayerCont.getIdentifier()).isPresent());
349         assertTrue(((ContainerNode) data).findChildByArg(buildPlaylistList.getIdentifier()).isPresent());
350
351         // config data absent
352         assertFalse(((ContainerNode) data).findChildByArg(buildLibraryCont.getIdentifier()).isPresent());
353     }
354
355     @Test
356     public void testPutData() {
357         final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(contextRef, iidBase);
358         final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
359
360         doReturn(immediateTrueFluentFuture()).when(read)
361                 .exists(LogicalDatastoreType.CONFIGURATION, iidBase);
362         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, iidBase, payload.getData());
363         final Response response = dataService.putData(null, payload, uriInfo);
364         assertNotNull(response);
365         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
366     }
367
368     @Test
369     public void testPutDataWithMountPoint() {
370         final InstanceIdentifierContext iidContext =
371             InstanceIdentifierContext.ofMountPointPath(mountPoint, contextRef, iidBase);
372         final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
373
374         doReturn(immediateTrueFluentFuture()).when(read)
375                 .exists(LogicalDatastoreType.CONFIGURATION, iidBase);
376         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, iidBase, payload.getData());
377         final Response response = dataService.putData(null, payload, uriInfo);
378         assertNotNull(response);
379         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
380     }
381
382     @Test
383     public void testPostData() {
384         final QName listQname = QName.create(baseQName, "playlist");
385         final QName listKeyQname = QName.create(baseQName, "name");
386         final NodeIdentifierWithPredicates nodeWithKey =
387                 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band");
388
389         doReturn(new MultivaluedHashMap<String, String>()).when(uriInfo).getQueryParameters();
390         final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(contextRef, iidBase);
391         final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, Builders.mapBuilder()
392             .withNodeIdentifier(new NodeIdentifier(listQname))
393             .withChild(Builders.mapEntryBuilder()
394                 .withNodeIdentifier(nodeWithKey)
395                 .withChild(ImmutableNodes.leafNode(QName.create(baseQName, "name"), "name of band"))
396                 .withChild(ImmutableNodes.leafNode(QName.create(baseQName, "description"), "band description"))
397                 .build())
398             .build());
399         final MapNode data = (MapNode) payload.getData();
400         final MapEntryNode entryNode = data.body().iterator().next();
401         final NodeIdentifierWithPredicates identifier = entryNode.getIdentifier();
402         final YangInstanceIdentifier node =
403                 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
404         doReturn(immediateFalseFluentFuture())
405                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
406         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
407         doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/15/")).when(uriInfo).getBaseUriBuilder();
408
409         final Response response = dataService.postData(null, payload, uriInfo);
410         assertEquals(201, response.getStatus());
411     }
412
413     @Test
414     public void testDeleteData() {
415         doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidBase);
416         doReturn(immediateTrueFluentFuture())
417                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
418         final Response response = dataService.deleteData("example-jukebox:jukebox");
419         assertNotNull(response);
420         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
421     }
422
423     /**
424      * Test of deleting data on mount point.
425      */
426     @Test
427     public void testDeleteDataMountPoint() {
428         doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidBase);
429         doReturn(immediateTrueFluentFuture())
430                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
431         final Response response =
432                 dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
433         assertNotNull(response);
434         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
435     }
436
437     @Test
438     public void testPatchData() {
439         final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(contextRef, iidBase);
440         final List<PatchEntity> entity = new ArrayList<>();
441         final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
442                 .node(containerPlayerQname)
443                 .node(leafQname)
444                 .build();
445         entity.add(new PatchEntity("create data", CREATE, iidBase, buildBaseCont));
446         entity.add(new PatchEntity("replace data", REPLACE, iidBase, buildBaseCont));
447         entity.add(new PatchEntity("delete data", DELETE, iidleaf));
448         final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
449
450         doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
451         doReturn(immediateFalseFluentFuture())
452                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
453         doReturn(immediateTrueFluentFuture())
454                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
455         final PatchStatusContext status = dataService.patchData(patch, uriInfo);
456         assertTrue(status.isOk());
457         assertEquals(3, status.getEditCollection().size());
458         assertEquals("replace data", status.getEditCollection().get(1).getEditId());
459     }
460
461     @Test
462     public void testPatchDataMountPoint() throws Exception {
463         final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofMountPointPath(mountPoint, contextRef,
464                 iidBase);
465         final List<PatchEntity> entity = new ArrayList<>();
466         final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
467                 .node(containerPlayerQname)
468                 .node(leafQname)
469                 .build();
470         entity.add(new PatchEntity("create data", CREATE, iidBase, buildBaseCont));
471         entity.add(new PatchEntity("replace data", REPLACE, iidBase, buildBaseCont));
472         entity.add(new PatchEntity("delete data", DELETE, iidleaf));
473         final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
474
475         doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
476         doReturn(immediateFalseFluentFuture())
477                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
478         doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
479
480         final PatchStatusContext status = dataService.patchData(patch, uriInfo);
481         assertTrue(status.isOk());
482         assertEquals(3, status.getEditCollection().size());
483         assertNull(status.getGlobalErrors());
484     }
485
486     @Test
487     public void testPatchDataDeleteNotExist() {
488         final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(contextRef, iidBase);
489         final List<PatchEntity> entity = new ArrayList<>();
490         final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(iidBase)
491                 .node(containerPlayerQname)
492                 .node(leafQname)
493                 .build();
494         entity.add(new PatchEntity("create data", CREATE, iidBase, buildBaseCont));
495         entity.add(new PatchEntity("remove data", REMOVE, iidleaf));
496         entity.add(new PatchEntity("delete data", DELETE, iidleaf));
497         final PatchContext patch = new PatchContext(iidContext, entity, "test patch id");
498
499         doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
500         doReturn(immediateFalseFluentFuture())
501                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidBase);
502         doReturn(immediateFalseFluentFuture())
503                 .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
504         doReturn(true).when(readWrite).cancel();
505         final PatchStatusContext status = dataService.patchData(patch, uriInfo);
506
507         assertFalse(status.isOk());
508         assertEquals(3, status.getEditCollection().size());
509         assertTrue(status.getEditCollection().get(0).isOk());
510         assertTrue(status.getEditCollection().get(1).isOk());
511         assertFalse(status.getEditCollection().get(2).isOk());
512         assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
513         final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
514         assertEquals("Data does not exist", errorMessage);
515     }
516
517     @Test
518     public void testGetRestconfStrategy() {
519         RestconfStrategy restconfStrategy = dataService.getRestconfStrategy(mountPoint);
520         assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
521
522         doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
523         restconfStrategy = dataService.getRestconfStrategy(mountPoint);
524         assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);
525     }
526 }