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.mockito.Mockito.doNothing;
11 import static org.mockito.Mockito.doReturn;
12 import static org.mockito.Mockito.verify;
13 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.mockito.Mock;
18 import org.mockito.Mockito;
19 import org.mockito.MockitoAnnotations;
20 import org.opendaylight.mdsal.common.api.CommitInfo;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
26 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
27 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
28 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
29 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
30 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
31 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
32 import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
33 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
38 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
44 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
48 public class PutDataTransactionUtilTest {
50 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
53 private DOMTransactionChain transactionChain;
55 private DOMDataTreeReadWriteTransaction readWrite;
57 private DOMDataTreeReadTransaction read;
59 private DOMDataTreeWriteTransaction write;
61 private DOMDataBroker mockDataBroker;
63 private TransactionChainHandler transactionChainHandler;
64 private SchemaContextRef refSchemaCtx;
65 private LeafNode buildLeaf;
66 private ContainerNode buildBaseCont;
67 private ContainerNode buildBaseContWithList;
68 private MapEntryNode buildListEntry;
69 private EffectiveModelContext schema;
70 private DataSchemaNode schemaNode;
71 private YangInstanceIdentifier iid;
72 private DataSchemaNode schemaNode2;
73 private YangInstanceIdentifier iid2;
74 private DataSchemaNode schemaNode3;
75 private YangInstanceIdentifier iid3;
78 public void setUp() throws Exception {
79 MockitoAnnotations.initMocks(this);
80 this.refSchemaCtx = new SchemaContextRef(
81 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT)));
82 this.schema = this.refSchemaCtx.get();
84 final QName baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
85 final QName containerQname = QName.create(baseQName, "player");
86 final QName leafQname = QName.create(baseQName, "gap");
87 final QName listQname = QName.create(baseQName, "playlist");
88 final QName listKeyQname = QName.create(baseQName, "name");
90 final NodeIdentifierWithPredicates nodeWithKey =
91 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band");
92 final NodeIdentifierWithPredicates nodeWithKey2 =
93 NodeIdentifierWithPredicates.of(listQname, listKeyQname, "name of band 2");
95 this.iid = YangInstanceIdentifier.builder()
100 this.schemaNode = DataSchemaContextTree.from(this.schema).getChild(this.iid).getDataSchemaNode();
102 this.iid2 = YangInstanceIdentifier.builder()
105 this.schemaNode2 = DataSchemaContextTree.from(this.schema).getChild(this.iid2).getDataSchemaNode();
107 this.iid3 = YangInstanceIdentifier.builder()
112 this.schemaNode3 = DataSchemaContextTree.from(this.schema).getChild(this.iid3).getDataSchemaNode();
114 this.buildLeaf = Builders.leafBuilder()
115 .withNodeIdentifier(new NodeIdentifier(leafQname))
118 final ContainerNode buildPlayerCont = Builders.containerBuilder()
119 .withNodeIdentifier(new NodeIdentifier(containerQname))
120 .withChild(this.buildLeaf)
122 this.buildBaseCont = Builders.containerBuilder()
123 .withNodeIdentifier(new NodeIdentifier(baseQName))
124 .withChild(buildPlayerCont)
126 final LeafNode<Object> content = Builders.leafBuilder()
127 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
128 .withValue("name of band")
130 final LeafNode<Object> content2 = Builders.leafBuilder()
131 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
132 .withValue("band description")
134 this.buildListEntry = Builders.mapEntryBuilder()
135 .withNodeIdentifier(nodeWithKey)
139 final LeafNode<Object> content3 = Builders.leafBuilder()
140 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
141 .withValue("name of band 2")
143 final LeafNode<Object> content4 = Builders.leafBuilder()
144 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
145 .withValue("band description 2")
147 final MapEntryNode buildListEntry2 = Builders.mapEntryBuilder()
148 .withNodeIdentifier(nodeWithKey2)
152 final MapNode buildList = Builders.mapBuilder()
153 .withNodeIdentifier(new NodeIdentifier(listQname))
154 .withChild(this.buildListEntry)
155 .withChild(buildListEntry2)
157 this.buildBaseContWithList = Builders.containerBuilder()
158 .withNodeIdentifier(new NodeIdentifier(baseQName))
159 .withChild(buildList)
162 Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
163 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
167 public void testValidInputData() throws Exception {
168 final InstanceIdentifierContext<DataSchemaNode> iidContext =
169 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
170 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
171 PutDataTransactionUtil.validInputData(iidContext.getSchemaNode(), payload);
175 public void testValidTopLevelNodeName() throws Exception {
176 InstanceIdentifierContext<DataSchemaNode> iidContext =
177 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
178 NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
179 PutDataTransactionUtil.validTopLevelNodeName(iidContext.getInstanceIdentifier(), payload);
181 iidContext = new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
182 payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
183 PutDataTransactionUtil.validTopLevelNodeName(iidContext.getInstanceIdentifier(), payload);
186 @Test(expected = RestconfDocumentedException.class)
187 public void testValidTopLevelNodeNamePathEmpty() throws Exception {
188 final InstanceIdentifierContext<DataSchemaNode> iidContext =
189 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
190 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
191 PutDataTransactionUtil.validTopLevelNodeName(YangInstanceIdentifier.empty(), payload);
194 @Test(expected = RestconfDocumentedException.class)
195 public void testValidTopLevelNodeNameWrongTopIdentifier() throws Exception {
196 final InstanceIdentifierContext<DataSchemaNode> iidContext =
197 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
198 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
199 PutDataTransactionUtil.validTopLevelNodeName(this.iid.getAncestor(1), payload);
203 public void testValidateListKeysEqualityInPayloadAndUri() throws Exception {
204 final InstanceIdentifierContext<DataSchemaNode> iidContext =
205 new InstanceIdentifierContext<>(this.iid3, this.schemaNode3, null, this.schema);
206 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildListEntry);
207 PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
211 public void testPutContainerData() throws Exception {
212 final InstanceIdentifierContext<DataSchemaNode> iidContext =
213 new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
214 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
216 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
217 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
218 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
219 doReturn(immediateFalseFluentFuture())
220 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
221 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
222 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
223 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
225 PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
226 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler), null,
228 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
229 payload.getInstanceIdentifierContext().getInstanceIdentifier());
230 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
231 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
235 public void testPutleafData() throws Exception {
236 final InstanceIdentifierContext<DataSchemaNode> iidContext =
237 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
238 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
240 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
241 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
242 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
243 doReturn(immediateFalseFluentFuture())
244 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid);
245 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
246 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
247 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
249 PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
250 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler), null,
252 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
253 payload.getInstanceIdentifierContext().getInstanceIdentifier());
254 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
255 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
259 public void testPutListData() throws Exception {
260 final InstanceIdentifierContext<DataSchemaNode> iidContext =
261 new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
262 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseContWithList);
264 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
265 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
266 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
267 doReturn(immediateFalseFluentFuture())
268 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
269 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
270 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
271 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
272 PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
273 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler), null,
275 verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
276 verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iid2, payload.getData());