NETCONF-514: Use exists instead of read for PUT
[netconf.git] / restconf / sal-rest-connector / src / test / java / org / opendaylight / restconf / restful / utils / PutDataTransactionUtilTest.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
9 package org.opendaylight.restconf.restful.utils;
10
11 import static org.mockito.Mockito.doNothing;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.verify;
14
15 import com.google.common.util.concurrent.Futures;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.mockito.Mock;
19 import org.mockito.MockitoAnnotations;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
23 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
24 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
25 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
26 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
27 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
28 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
29 import org.opendaylight.restconf.common.references.SchemaContextRef;
30 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
37 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
38 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
39 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
41 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
42
43 public class PutDataTransactionUtilTest {
44
45     private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
46
47     @Mock
48     private DOMTransactionChain transactionChain;
49     @Mock
50     private DOMDataReadWriteTransaction readWrite;
51     @Mock
52     private DOMDataReadOnlyTransaction read;
53     @Mock
54     private DOMDataWriteTransaction write;
55
56
57     private SchemaContextRef refSchemaCtx;
58     private LeafNode buildLeaf;
59     private ContainerNode buildBaseCont;
60     private ContainerNode buildBaseContWithList;
61     private MapEntryNode buildListEntry;
62     private SchemaContext schema;
63     private DataSchemaNode schemaNode;
64     private YangInstanceIdentifier iid;
65     private DataSchemaNode schemaNode2;
66     private YangInstanceIdentifier iid2;
67     private DataSchemaNode schemaNode3;
68     private YangInstanceIdentifier iid3;
69
70     @Before
71     public void setUp() throws Exception {
72         MockitoAnnotations.initMocks(this);
73         this.refSchemaCtx = new SchemaContextRef(
74                 YangParserTestUtils.parseYangSources(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT)));
75         this.schema = this.refSchemaCtx.get();
76
77         final QName baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
78         final QName containerQname = QName.create(baseQName, "player");
79         final QName leafQname = QName.create(baseQName, "gap");
80         final QName listQname = QName.create(baseQName, "playlist");
81         final QName listKeyQname = QName.create(baseQName, "name");
82
83         final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeWithKey =
84                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(listQname, listKeyQname, "name of band");
85         final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeWithKey2 =
86                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(listQname, listKeyQname, "name of band 2");
87
88         this.iid = YangInstanceIdentifier.builder()
89                 .node(baseQName)
90                 .node(containerQname)
91                 .node(leafQname)
92                 .build();
93         this.schemaNode = DataSchemaContextTree.from(this.schema).getChild(this.iid).getDataSchemaNode();
94
95         this.iid2 = YangInstanceIdentifier.builder()
96                 .node(baseQName)
97                 .build();
98         this.schemaNode2 = DataSchemaContextTree.from(this.schema).getChild(this.iid2).getDataSchemaNode();
99
100         this.iid3 = YangInstanceIdentifier.builder()
101                 .node(baseQName)
102                 .node(listQname)
103                 .node(nodeWithKey)
104                 .build();
105         this.schemaNode3 = DataSchemaContextTree.from(this.schema).getChild(this.iid3).getDataSchemaNode();
106
107         this.buildLeaf = Builders.leafBuilder()
108                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(leafQname))
109                 .withValue(0.2)
110                 .build();
111         final ContainerNode buildPlayerCont = Builders.containerBuilder()
112                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerQname))
113                 .withChild(this.buildLeaf)
114                 .build();
115         this.buildBaseCont = Builders.containerBuilder()
116                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(baseQName))
117                 .withChild(buildPlayerCont)
118                 .build();
119         final LeafNode<Object> content = Builders.leafBuilder()
120                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(baseQName, "name")))
121                 .withValue("name of band")
122                 .build();
123         final LeafNode<Object> content2 = Builders.leafBuilder()
124                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(baseQName, "description")))
125                 .withValue("band description")
126                 .build();
127         this.buildListEntry = Builders.mapEntryBuilder()
128                 .withNodeIdentifier(nodeWithKey)
129                 .withChild(content)
130                 .withChild(content2)
131                 .build();
132         final LeafNode<Object> content3 = Builders.leafBuilder()
133                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(baseQName, "name")))
134                 .withValue("name of band 2")
135                 .build();
136         final LeafNode<Object> content4 = Builders.leafBuilder()
137                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(baseQName, "description")))
138                 .withValue("band description 2")
139                 .build();
140         final MapEntryNode buildListEntry2 = Builders.mapEntryBuilder()
141                 .withNodeIdentifier(nodeWithKey2)
142                 .withChild(content3)
143                 .withChild(content4)
144                 .build();
145         final MapNode buildList = Builders.mapBuilder()
146                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listQname))
147                 .withChild(this.buildListEntry)
148                 .withChild(buildListEntry2)
149                 .build();
150         this.buildBaseContWithList = Builders.containerBuilder()
151                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(baseQName))
152                 .withChild(buildList)
153                 .build();
154
155     }
156
157     @Test
158     public void testValidInputData() throws Exception {
159         final InstanceIdentifierContext<DataSchemaNode> iidContext =
160                 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
161         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
162         PutDataTransactionUtil.validInputData(iidContext.getSchemaNode(), payload);
163     }
164
165     @Test
166     public void testValidTopLevelNodeName() throws Exception {
167         InstanceIdentifierContext<DataSchemaNode> iidContext =
168                 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
169         NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
170         PutDataTransactionUtil.validTopLevelNodeName(iidContext.getInstanceIdentifier(), payload);
171
172         iidContext = new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
173         payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
174         PutDataTransactionUtil.validTopLevelNodeName(iidContext.getInstanceIdentifier(), payload);
175     }
176
177     @Test(expected = RestconfDocumentedException.class)
178     public void testValidTopLevelNodeNamePathEmpty() throws Exception {
179         final InstanceIdentifierContext<DataSchemaNode> iidContext =
180                 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
181         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
182         PutDataTransactionUtil.validTopLevelNodeName(YangInstanceIdentifier.EMPTY, payload);
183     }
184
185     @Test(expected = RestconfDocumentedException.class)
186     public void testValidTopLevelNodeNameWrongTopIdentifier() throws Exception {
187         final InstanceIdentifierContext<DataSchemaNode> iidContext =
188                 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
189         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
190         PutDataTransactionUtil.validTopLevelNodeName(this.iid.getAncestor(1), payload);
191     }
192
193     @Test
194     public void testValidateListKeysEqualityInPayloadAndUri() throws Exception {
195         final InstanceIdentifierContext<DataSchemaNode> iidContext =
196                 new InstanceIdentifierContext<>(this.iid3, this.schemaNode3, null, this.schema);
197         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildListEntry);
198         PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
199     }
200
201     @Test
202     public void testPutContainerData() throws Exception {
203         final InstanceIdentifierContext<DataSchemaNode> iidContext =
204                 new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
205         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
206
207         doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
208         doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
209         doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
210         doReturn(Futures.immediateCheckedFuture(Boolean.FALSE))
211                 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
212         doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
213                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
214         doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
215
216         PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
217                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain), null,
218                 null);
219         verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
220                 payload.getInstanceIdentifierContext().getInstanceIdentifier());
221         verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
222                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
223     }
224
225     @Test
226     public void testPutleafData() throws Exception {
227         final InstanceIdentifierContext<DataSchemaNode> iidContext =
228                 new InstanceIdentifierContext<>(this.iid, this.schemaNode, null, this.schema);
229         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildLeaf);
230
231         doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
232         doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
233         doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
234         doReturn(Futures.immediateCheckedFuture(Boolean.FALSE))
235                 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid);
236         doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
237                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
238         doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
239
240         PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
241                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain), null,
242                 null);
243         verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION,
244                 payload.getInstanceIdentifierContext().getInstanceIdentifier());
245         verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
246                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
247     }
248
249     @Test
250     public void testPutListData() throws Exception {
251         final InstanceIdentifierContext<DataSchemaNode> iidContext =
252                 new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
253         final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseContWithList);
254
255         doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
256         doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
257         doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
258         doReturn(Futures.immediateCheckedFuture(Boolean.FALSE))
259                 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
260         doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
261                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
262         doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
263         PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
264                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain), null,
265                 null);
266         verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
267         verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iid2, payload.getData());
268     }
269
270 }
271