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.hamcrest.CoreMatchers.containsString;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.verify;
18 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
19 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URLDecoder;
23 import java.util.Collection;
24 import javax.ws.rs.core.Response;
25 import javax.ws.rs.core.UriBuilder;
26 import javax.ws.rs.core.UriInfo;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.mockito.Mock;
30 import org.mockito.Mockito;
31 import org.mockito.MockitoAnnotations;
32 import org.opendaylight.mdsal.common.api.CommitInfo;
33 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
34 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
35 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
36 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
37 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
38 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
39 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
40 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
41 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
42 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
43 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
44 import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
45 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
46 import org.opendaylight.yangtools.yang.common.QName;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
49 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
50 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
51 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
53 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
54 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
55 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
56 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
57 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
58 import org.w3c.dom.DOMException;
60 public class PostDataTransactionUtilTest {
62 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
65 private DOMTransactionChain transactionChain;
67 private DOMDataTreeReadWriteTransaction readWrite;
69 private DOMDataTreeReadTransaction read;
71 private DOMDataTreeWriteTransaction write;
73 private UriInfo uriInfo;
75 private UriBuilder uriBuilder;
77 private DOMDataBroker mockDataBroker;
79 private TransactionChainHandler transactionChainHandler;
80 private SchemaContextRef refSchemaCtx;
81 private ContainerNode buildBaseCont;
82 private EffectiveModelContext schema;
83 private YangInstanceIdentifier iid2;
84 private YangInstanceIdentifier iidList;
85 private MapNode buildList;
88 public void setUp() throws Exception {
89 MockitoAnnotations.initMocks(this);
90 this.refSchemaCtx = new SchemaContextRef(
91 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT)));
92 this.schema = this.refSchemaCtx.get();
94 final QName baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
95 final QName containerQname = QName.create(baseQName, "player");
96 final QName leafQname = QName.create(baseQName, "gap");
97 final QName listQname = QName.create(baseQName, "playlist");
98 final QName listKeyQname = QName.create(baseQName, "name");
99 final NodeIdentifierWithPredicates nodeWithKey = NodeIdentifierWithPredicates.of(listQname, listKeyQname,
101 this.iid2 = YangInstanceIdentifier.builder()
104 this.iidList = YangInstanceIdentifier.builder()
109 final LeafNode<?> buildLeaf = Builders.leafBuilder()
110 .withNodeIdentifier(new NodeIdentifier(leafQname))
113 final ContainerNode buildPlayerCont = Builders.containerBuilder()
114 .withNodeIdentifier(new NodeIdentifier(containerQname))
115 .withChild(buildLeaf)
117 this.buildBaseCont = Builders.containerBuilder()
118 .withNodeIdentifier(new NodeIdentifier(baseQName))
119 .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 final MapEntryNode mapEntryNode = Builders.mapEntryBuilder()
131 .withNodeIdentifier(nodeWithKey)
135 this.buildList = Builders.mapBuilder()
136 .withNodeIdentifier(new NodeIdentifier(listQname))
137 .withChild(mapEntryNode)
140 doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/16/")).when(this.uriInfo).getBaseUriBuilder();
141 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
142 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
144 Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
145 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
149 public void testPostContainerData() {
150 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
151 new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
152 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
154 doReturn(immediateFalseFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
156 final NodeIdentifier identifier =
157 ((ContainerNode) ((Collection<?>) payload.getData().getValue()).iterator().next()).getIdentifier();
158 final YangInstanceIdentifier node =
159 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
160 doReturn(immediateFalseFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
161 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
162 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
163 final TransactionVarsWrapper wrapper =
164 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler);
165 final Response response =
166 PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx, null, null);
167 assertEquals(201, response.getStatus());
168 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
169 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
170 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
174 public void testPostListData() throws UnsupportedEncodingException {
175 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
176 new InstanceIdentifierContext<>(this.iidList, null, null, this.schema);
177 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildList);
179 final MapNode data = (MapNode) payload.getData();
180 final NodeIdentifierWithPredicates identifier = data.getValue().iterator().next().getIdentifier();
181 final YangInstanceIdentifier node =
182 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
183 doReturn(immediateFalseFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
184 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
185 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
186 final TransactionVarsWrapper wrapper =
187 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler);
188 final Response response =
189 PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx, null, null);
190 assertEquals(201, response.getStatus());
191 assertThat(URLDecoder.decode(response.getLocation().toString(), "UTF-8"),
192 containsString(identifier.getValue(identifier.keySet().iterator().next()).toString()));
193 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
194 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, data.getValue().iterator().next());
198 public void testPostDataFail() {
199 final InstanceIdentifierContext<? extends SchemaNode> iidContext =
200 new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
201 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
203 doReturn(immediateFalseFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
205 final NodeIdentifier identifier =
206 ((ContainerNode) ((Collection<?>) payload.getData().getValue()).iterator().next()).getIdentifier();
207 final YangInstanceIdentifier node =
208 payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
209 doReturn(immediateFalseFluentFuture()).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
210 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
211 final DOMException domException = new DOMException((short) 414, "Post request failed");
212 doReturn(immediateFailedFluentFuture(domException)).when(this.readWrite).commit();
213 final TransactionVarsWrapper wrapper =
214 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler);
217 PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx, null, null);
218 fail("Expected RestconfDocumentedException");
219 } catch (final RestconfDocumentedException e) {
220 assertEquals(1, e.getErrors().size());
221 assertTrue(e.getErrors().get(0).getErrorInfo().contains(domException.getMessage()));
224 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
225 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
226 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());