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
9 package org.opendaylight.restconf.restful.services.impl;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.Matchers.any;
17 import static org.mockito.Mockito.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.mock;
20 import com.google.common.base.Optional;
21 import com.google.common.util.concurrent.CheckedFuture;
22 import com.google.common.util.concurrent.Futures;
23 import java.lang.reflect.Field;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.List;
28 import javax.ws.rs.core.MultivaluedHashMap;
29 import javax.ws.rs.core.MultivaluedMap;
30 import javax.ws.rs.core.Response;
31 import javax.ws.rs.core.UriBuilder;
32 import javax.ws.rs.core.UriInfo;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.mockito.Mock;
36 import org.mockito.Mockito;
37 import org.mockito.MockitoAnnotations;
38 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
39 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
40 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
41 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
42 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
43 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
44 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
45 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
46 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
47 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
48 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
49 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
50 import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
51 import org.opendaylight.netconf.sal.restconf.impl.PATCHEntity;
52 import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
53 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
54 import org.opendaylight.restconf.RestConnectorProvider;
55 import org.opendaylight.restconf.common.references.SchemaContextRef;
56 import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
57 import org.opendaylight.restconf.handlers.SchemaContextHandler;
58 import org.opendaylight.restconf.handlers.TransactionChainHandler;
59 import org.opendaylight.yangtools.yang.common.QName;
60 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
61 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
62 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
63 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
64 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
65 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
66 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
67 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
68 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
69 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
71 public class RestconfDataServiceImplTest {
73 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
75 private ContainerNode buildBaseCont;
76 private ContainerNode buildBaseContConfig;
77 private ContainerNode buildBaseContOperational;
78 private SchemaContextRef contextRef;
79 private YangInstanceIdentifier iidBase;
80 private DataSchemaNode schemaNode;
81 private RestconfDataServiceImpl dataService;
82 private QName baseQName;
83 private QName containerPlayerQname;
84 private QName leafQname;
85 private ContainerNode buildPlayerCont;
86 private ContainerNode buildLibraryCont;
87 private MapNode buildPlaylistList;
90 private TransactionChainHandler transactionChainHandler;
92 private DOMTransactionChain domTransactionChain;
94 private UriInfo uriInfo;
96 private DOMDataReadWriteTransaction readWrite;
98 private DOMDataReadOnlyTransaction read;
100 private DOMDataWriteTransaction write;
102 private DOMMountPointServiceHandler mountPointServiceHandler;
104 private DOMMountPointService mountPointService;
106 private DOMMountPoint mountPoint;
108 private DOMDataBroker mountDataBroker;
110 private DOMTransactionChain transactionChain;
113 public void setUp() throws Exception {
114 MockitoAnnotations.initMocks(this);
116 final MultivaluedMap<String, String> value = Mockito.mock(MultivaluedMap.class);
117 Mockito.when(value.entrySet()).thenReturn(new HashSet<>());
118 Mockito.when(this.uriInfo.getQueryParameters()).thenReturn(value);
120 this.baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
121 this.containerPlayerQname = QName.create(this.baseQName, "player");
122 this.leafQname = QName.create(this.baseQName, "gap");
124 final QName containerLibraryQName = QName.create(this.baseQName, "library");
125 final QName listPlaylistQName = QName.create(this.baseQName, "playlist");
127 final LeafNode buildLeaf = Builders.leafBuilder()
128 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.leafQname))
132 this.buildPlayerCont = Builders.containerBuilder()
133 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.containerPlayerQname))
134 .withChild(buildLeaf)
137 this.buildLibraryCont = Builders.containerBuilder()
138 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerLibraryQName))
141 this.buildPlaylistList = Builders.mapBuilder()
142 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listPlaylistQName))
145 this.buildBaseCont = Builders.containerBuilder()
146 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
147 .withChild(this.buildPlayerCont)
150 // config contains one child the same as in operational and one additional
151 this.buildBaseContConfig = Builders.containerBuilder()
152 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
153 .withChild(this.buildPlayerCont)
154 .withChild(this.buildLibraryCont)
157 // operational contains one child the same as in config and one additional
158 this.buildBaseContOperational = Builders.containerBuilder()
159 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
160 .withChild(this.buildPlayerCont)
161 .withChild(this.buildPlaylistList)
164 this.iidBase = YangInstanceIdentifier.builder()
165 .node(this.baseQName)
168 this.contextRef = new SchemaContextRef(TestRestconfUtils.loadSchemaContext(PATH_FOR_NEW_SCHEMA_CONTEXT));
169 this.schemaNode = DataSchemaContextTree.from(this.contextRef.get()).getChild(this.iidBase).getDataSchemaNode();
171 final TransactionChainHandler txHandler = Mockito.mock(TransactionChainHandler.class);
172 final DOMTransactionChain domTx = Mockito.mock(DOMTransactionChain.class);
173 Mockito.when(txHandler.get()).thenReturn(domTx);
174 final DOMDataWriteTransaction wTx = Mockito.mock(DOMDataWriteTransaction.class);
175 Mockito.when(domTx.newWriteOnlyTransaction()).thenReturn(wTx);
176 final CheckedFuture checked = Mockito.mock(CheckedFuture.class);
177 Mockito.when(wTx.submit()).thenReturn(checked);
178 final Object valueObj = null;
179 Mockito.when(checked.checkedGet()).thenReturn(valueObj);
180 final SchemaContextHandler schemaContextHandler = new SchemaContextHandler(txHandler);
182 schemaContextHandler.onGlobalContextUpdated(this.contextRef.get());
183 this.dataService = new RestconfDataServiceImpl(schemaContextHandler, this.transactionChainHandler, this.mountPointServiceHandler);
184 doReturn(this.domTransactionChain).when(this.transactionChainHandler).get();
185 doReturn(this.read).when(this.domTransactionChain).newReadOnlyTransaction();
186 doReturn(this.readWrite).when(this.domTransactionChain).newReadWriteTransaction();
187 doReturn(this.write).when(this.domTransactionChain).newWriteOnlyTransaction();
188 doReturn(this.mountPointService).when(this.mountPointServiceHandler).get();
189 doReturn(Optional.of(this.mountPoint)).when(this.mountPointService).getMountPoint(any(YangInstanceIdentifier.class));
190 doReturn(this.contextRef.get()).when(this.mountPoint).getSchemaContext();
191 doReturn(Optional.of(this.mountDataBroker)).when(this.mountPoint).getService(DOMDataBroker.class);
192 doReturn(this.transactionChain).when(this.mountDataBroker).createTransactionChain(any(TransactionChainListener.class));
193 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
194 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
198 public void testReadData() {
199 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
200 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
201 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
202 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
203 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
204 assertNotNull(response);
205 assertEquals(200, response.getStatus());
206 assertEquals(this.buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
210 * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
211 * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
214 public void testReadDataMountPoint() {
215 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
216 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
217 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
218 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
219 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
221 final Response response = this.dataService.readData(
222 "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", this.uriInfo);
224 assertNotNull(response);
225 assertEquals(200, response.getStatus());
227 // response must contain all child nodes from config and operational containers merged in one container
228 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
229 assertTrue(data instanceof ContainerNode);
230 assertEquals(3, ((ContainerNode) data).getValue().size());
231 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
232 assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
233 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
236 @Test(expected = RestconfDocumentedException.class)
237 public void testReadDataNoData() {
238 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
239 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION,
241 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.OPERATIONAL,
243 this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
247 * Read data from config datastore according to content parameter
250 public void testReadDataConfigTest() {
251 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
252 parameters.put("content", Collections.singletonList("config"));
254 doReturn(parameters).when(this.uriInfo).getQueryParameters();
255 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
256 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
257 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
258 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
260 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
262 assertNotNull(response);
263 assertEquals(200, response.getStatus());
265 // response must contain only config data
266 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
268 // config data present
269 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
270 assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
273 assertFalse(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
277 * Read data from operational datastore according to content parameter
280 public void testReadDataOperationalTest() {
281 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
282 parameters.put("content", Collections.singletonList("nonconfig"));
284 doReturn(parameters).when(this.uriInfo).getQueryParameters();
285 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
286 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
287 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
288 .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
290 final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
292 assertNotNull(response);
293 assertEquals(200, response.getStatus());
295 // response must contain only operational data
296 final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
298 // state data present
299 assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
300 assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
302 // config data absent
303 assertFalse(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
307 public void testPutData() {
308 final InstanceIdentifierContext<DataSchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
309 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
311 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
312 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
313 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
314 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
315 final Response response = this.dataService.putData(null, payload, this.uriInfo);
316 assertNotNull(response);
317 assertEquals(200, response.getStatus());
321 public void testPutDataWithMountPoint() {
322 final DOMDataBroker dataBroker = Mockito.mock(DOMDataBroker.class);
323 final DOMMountPoint mountPoint = Mockito.mock(DOMMountPoint.class);
324 doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
325 doReturn(this.transactionChainHandler.get()).when(dataBroker).createTransactionChain(RestConnectorProvider.transactionListener);
326 final InstanceIdentifierContext<DataSchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, mountPoint, this.contextRef.get());
327 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
329 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
330 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
331 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
332 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
333 final Response response = this.dataService.putData(null, payload, this.uriInfo);
334 assertNotNull(response);
335 assertEquals(200, response.getStatus());
339 public void testPostData() {
340 final QName listQname = QName.create(this.baseQName, "playlist");
341 final QName listKeyQname = QName.create(this.baseQName, "name");
342 final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeWithKey =
343 new YangInstanceIdentifier.NodeIdentifierWithPredicates(listQname, listKeyQname, "name of band");
344 final LeafNode<Object> content = Builders.leafBuilder()
345 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(this.baseQName, "name")))
346 .withValue("name of band")
348 final LeafNode<Object> content2 = Builders.leafBuilder()
349 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(this.baseQName, "description")))
350 .withValue("band description")
352 final MapEntryNode mapEntryNode = Builders.mapEntryBuilder()
353 .withNodeIdentifier(nodeWithKey)
357 final MapNode buildList = Builders.mapBuilder()
358 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listQname))
359 .withChild(mapEntryNode)
362 doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
363 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, null, null, this.contextRef.get());
364 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, buildList);
365 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
366 final MapNode data = (MapNode) payload.getData();
367 final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier = data.getValue().iterator().next().getIdentifier();
368 final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
369 doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
370 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
371 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
372 doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/15/")).when(this.uriInfo).getBaseUriBuilder();
374 final Response response = this.dataService.postData(null, payload, this.uriInfo);
375 assertEquals(201, response.getStatus());
379 public void testDeleteData() {
380 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
381 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
382 doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
383 final Response response = this.dataService.deleteData("example-jukebox:jukebox");
384 assertNotNull(response);
385 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
389 * Test of deleting data on mount point
392 public void testDeleteDataMountPoint() {
393 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
394 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
395 doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
396 final Response response = this.dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
397 assertNotNull(response);
398 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
402 public void testPatchData() throws Exception {
403 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
404 final List<PATCHEntity> entity = new ArrayList<>();
405 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
406 .node(this.containerPlayerQname)
407 .node(this.leafQname)
409 entity.add(new PATCHEntity("create data", "CREATE", this.iidBase, this.buildBaseCont));
410 entity.add(new PATCHEntity("replace data", "REPLACE", this.iidBase, this.buildBaseCont));
411 entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
412 final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
414 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
415 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
416 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
417 doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
418 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
419 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
420 doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
421 doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
422 final PATCHStatusContext status = this.dataService.patchData(patch, this.uriInfo);
423 assertTrue(status.isOk());
424 assertEquals(3, status.getEditCollection().size());
425 assertEquals("replace data", status.getEditCollection().get(1).getEditId());
429 public void testPatchDataMountPoint() throws Exception {
430 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(
431 this.iidBase, this.schemaNode, this.mountPoint, this.contextRef.get());
432 final List<PATCHEntity> entity = new ArrayList<>();
433 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
434 .node(this.containerPlayerQname)
435 .node(this.leafQname)
437 entity.add(new PATCHEntity("create data", "CREATE", this.iidBase, this.buildBaseCont));
438 entity.add(new PATCHEntity("replace data", "REPLACE", this.iidBase, this.buildBaseCont));
439 entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
440 final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
442 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
443 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
444 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
445 doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
446 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
447 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
448 doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
449 doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
451 final PATCHStatusContext status = this.dataService.patchData(patch, this.uriInfo);
452 assertTrue(status.isOk());
453 assertEquals(3, status.getEditCollection().size());
454 assertNull(status.getGlobalErrors());
458 public void testPatchDataDeleteNotExist() throws Exception {
459 final Field handler = RestConnectorProvider.class.getDeclaredField("transactionChainHandler");
460 final Field broker = RestConnectorProvider.class.getDeclaredField("dataBroker");
462 handler.setAccessible(true);
463 handler.set(RestConnectorProvider.class, mock(TransactionChainHandler.class));
465 broker.setAccessible(true);
466 broker.set(RestConnectorProvider.class, mock(DOMDataBroker.class));
467 final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
468 final List<PATCHEntity> entity = new ArrayList<>();
469 final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
470 .node(this.containerPlayerQname)
471 .node(this.leafQname)
473 entity.add(new PATCHEntity("create data", "CREATE", this.iidBase, this.buildBaseCont));
474 entity.add(new PATCHEntity("remove data", "REMOVE", iidleaf));
475 entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
476 final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
478 doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
479 .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
480 doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
481 doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
482 doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
483 doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
484 doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
485 doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
486 doReturn(true).when(this.readWrite).cancel();
487 final PATCHStatusContext status = this.dataService.patchData(patch, this.uriInfo);
489 handler.set(RestConnectorProvider.class, null);
490 handler.setAccessible(false);
492 broker.set(RestConnectorProvider.class, null);
493 broker.setAccessible(false);
495 assertFalse(status.isOk());
496 assertEquals(3, status.getEditCollection().size());
497 assertTrue(status.getEditCollection().get(0).isOk());
498 assertTrue(status.getEditCollection().get(1).isOk());
499 assertFalse(status.getEditCollection().get(2).isOk());
500 assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
501 final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
502 assertEquals("Data does not exist", errorMessage);