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.utils;
10 import static org.junit.Assert.assertThrows;
11 import static org.mockito.Mockito.doNothing;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.verify;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
16 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
18 import com.google.common.util.concurrent.Futures;
19 import java.util.Optional;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.Mock;
24 import org.mockito.junit.MockitoJUnitRunner;
25 import org.opendaylight.mdsal.common.api.CommitInfo;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
28 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
29 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
30 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
31 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
32 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
33 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
34 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
35 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
36 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
37 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
38 import org.opendaylight.restconf.nb.rfc8040.rests.services.impl.RestconfDataServiceImpl;
39 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
40 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
41 import org.opendaylight.yangtools.yang.common.QName;
42 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
43 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
45 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
47 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
48 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
49 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
50 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
51 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
52 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
54 @RunWith(MockitoJUnitRunner.StrictStubs.class)
55 public class PutDataTransactionUtilTest {
56 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
59 private DOMDataTreeReadWriteTransaction readWrite;
61 private DOMDataTreeReadTransaction read;
63 private DOMDataTreeWriteTransaction write;
65 private DOMDataBroker mockDataBroker;
67 private NetconfDataTreeService netconfService;
69 private LeafNode<?> buildLeaf;
70 private ContainerNode buildBaseCont;
71 private ContainerNode buildBaseContWithList;
72 private MapEntryNode buildListEntry;
73 private EffectiveModelContext schema;
74 private YangInstanceIdentifier iid;
75 private YangInstanceIdentifier iid2;
76 private YangInstanceIdentifier iid3;
79 public void setUp() throws Exception {
81 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
83 final QName baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
84 final QName containerQname = QName.create(baseQName, "player");
85 final QName leafQname = QName.create(baseQName, "gap");
86 final QName listQname = QName.create(baseQName, "playlist");
87 final QName listKeyQname = QName.create(baseQName, "name");
89 final NodeIdentifierWithPredicates nodeWithKey =
90 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band");
91 final NodeIdentifierWithPredicates nodeWithKey2 =
92 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band 2");
94 iid = YangInstanceIdentifier.builder()
100 iid2 = YangInstanceIdentifier.builder()
104 iid3 = YangInstanceIdentifier.builder()
110 buildLeaf = Builders.leafBuilder()
111 .withNodeIdentifier(new NodeIdentifier(leafQname))
114 final ContainerNode buildPlayerCont = Builders.containerBuilder()
115 .withNodeIdentifier(new NodeIdentifier(containerQname))
116 .withChild(buildLeaf)
118 buildBaseCont = Builders.containerBuilder()
119 .withNodeIdentifier(new NodeIdentifier(baseQName))
120 .withChild(buildPlayerCont)
122 final LeafNode<Object> content = Builders.leafBuilder()
123 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
124 .withValue("name of band")
126 final LeafNode<Object> content2 = Builders.leafBuilder()
127 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
128 .withValue("band description")
130 buildListEntry = Builders.mapEntryBuilder()
131 .withNodeIdentifier(nodeWithKey)
135 final LeafNode<Object> content3 = Builders.leafBuilder()
136 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
137 .withValue("name of band 2")
139 final LeafNode<Object> content4 = Builders.leafBuilder()
140 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
141 .withValue("band description 2")
143 final MapEntryNode buildListEntry2 = Builders.mapEntryBuilder()
144 .withNodeIdentifier(nodeWithKey2)
148 final MapNode buildList = Builders.mapBuilder()
149 .withNodeIdentifier(new NodeIdentifier(listQname))
150 .withChild(buildListEntry)
151 .withChild(buildListEntry2)
153 buildBaseContWithList = Builders.containerBuilder()
154 .withNodeIdentifier(new NodeIdentifier(baseQName))
155 .withChild(buildList)
158 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).lock();
159 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
163 public void testValidInputData() {
164 RestconfDataServiceImpl.validInputData(true, NormalizedNodePayload.of(
165 InstanceIdentifierContext.ofLocalPath(schema, iid), buildLeaf));
169 public void testValidTopLevelNodeName() {
170 RestconfDataServiceImpl.validTopLevelNodeName(iid, NormalizedNodePayload.of(
171 InstanceIdentifierContext.ofLocalPath(schema, iid), buildLeaf));
172 RestconfDataServiceImpl.validTopLevelNodeName(iid2, NormalizedNodePayload.of(
173 InstanceIdentifierContext.ofLocalPath(schema, iid2), buildBaseCont));
177 public void testValidTopLevelNodeNamePathEmpty() {
178 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid);
179 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildLeaf);
181 // FIXME: more asserts
182 assertThrows(RestconfDocumentedException.class,
183 () -> RestconfDataServiceImpl.validTopLevelNodeName(YangInstanceIdentifier.of(), payload));
187 public void testValidTopLevelNodeNameWrongTopIdentifier() {
188 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid);
189 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildLeaf);
191 // FIXME: more asserts
192 assertThrows(RestconfDocumentedException.class,
193 () -> RestconfDataServiceImpl.validTopLevelNodeName(iid.getAncestor(1), payload));
197 public void testValidateListKeysEqualityInPayloadAndUri() {
198 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid3);
199 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildListEntry);
200 RestconfDataServiceImpl.validateListKeysEqualityInPayloadAndUri(payload);
204 public void testPutContainerData() {
205 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
206 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
208 doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
209 doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
210 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, iid2);
211 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData());
212 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
214 PutDataTransactionUtil.putData(payload, schema, new MdsalRestconfStrategy(mockDataBroker),
215 WriteDataParams.empty());
216 verify(read).exists(LogicalDatastoreType.CONFIGURATION, iid2);
217 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData());
221 public void testPutCreateContainerData() {
222 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
223 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
225 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(iid2);
226 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
227 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
228 .replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());
230 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
231 WriteDataParams.empty());
232 verify(netconfService).lock();
233 verify(netconfService).getConfig(iid2);
234 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());
238 public void testPutReplaceContainerData() {
239 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
240 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseCont);
242 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService).getConfig(iid2);
243 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
244 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
245 .replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());
247 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
248 WriteDataParams.empty());
249 verify(netconfService).getConfig(iid2);
250 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());
254 public void testPutLeafData() {
255 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid);
256 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildLeaf);
258 doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
259 doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
260 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, iid);
261 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid, payload.getData());
262 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
264 PutDataTransactionUtil.putData(payload, schema, new MdsalRestconfStrategy(mockDataBroker),
265 WriteDataParams.empty());
266 verify(read).exists(LogicalDatastoreType.CONFIGURATION, iid);
267 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid, payload.getData());
271 public void testPutCreateLeafData() {
272 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid);
273 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildLeaf);
275 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(iid);
276 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
277 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
278 .replace(LogicalDatastoreType.CONFIGURATION, iid, payload.getData(), Optional.empty());
280 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
281 WriteDataParams.empty());
282 verify(netconfService).getConfig(iid);
283 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid, payload.getData(), Optional.empty());
287 public void testPutReplaceLeafData() {
288 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid);
289 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildLeaf);
291 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService).getConfig(iid);
292 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
293 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
294 .replace(LogicalDatastoreType.CONFIGURATION, iid, payload.getData(), Optional.empty());
296 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
297 WriteDataParams.empty());
298 verify(netconfService).getConfig(iid);
299 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid, payload.getData(), Optional.empty());
303 public void testPutListData() {
304 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
305 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseContWithList);
307 doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
308 doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
309 doReturn(immediateFalseFluentFuture())
310 .when(read).exists(LogicalDatastoreType.CONFIGURATION, iid2);
311 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData());
312 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
313 PutDataTransactionUtil.putData(payload, schema, new MdsalRestconfStrategy(mockDataBroker),
314 WriteDataParams.empty());
315 verify(read).exists(LogicalDatastoreType.CONFIGURATION, iid2);
316 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData());
320 public void testPutCreateListData() {
321 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
322 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseContWithList);
324 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService)
326 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
327 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
328 .replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());
330 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
331 WriteDataParams.empty());
332 verify(netconfService).getConfig(iid2);
333 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid2,
334 payload.getData(), Optional.empty());
338 public void testPutReplaceListData() {
339 final InstanceIdentifierContext iidContext = InstanceIdentifierContext.ofLocalPath(schema, iid2);
340 final NormalizedNodePayload payload = NormalizedNodePayload.of(iidContext, buildBaseContWithList);
342 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService)
344 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
345 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
346 .replace(LogicalDatastoreType.CONFIGURATION,
347 iid2, payload.getData(), Optional.empty());
349 PutDataTransactionUtil.putData(payload, schema, new NetconfRestconfStrategy(netconfService),
350 WriteDataParams.empty());
351 verify(netconfService).getConfig(iid2);
352 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, iid2, payload.getData(), Optional.empty());