27a0a0631f044da279b7555a16da20e8d76ba2c5
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / 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 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
9
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;
14
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.SchemaContext;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47
48 public class PutDataTransactionUtilTest {
49
50     private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
51
52     @Mock
53     private DOMTransactionChain transactionChain;
54     @Mock
55     private DOMDataTreeReadWriteTransaction readWrite;
56     @Mock
57     private DOMDataTreeReadTransaction read;
58     @Mock
59     private DOMDataTreeWriteTransaction write;
60     @Mock
61     private DOMDataBroker mockDataBroker;
62
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 SchemaContext 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;
76
77     @Before
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();
83
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");
89
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");
94
95         this.iid = YangInstanceIdentifier.builder()
96                 .node(baseQName)
97                 .node(containerQname)
98                 .node(leafQname)
99                 .build();
100         this.schemaNode = DataSchemaContextTree.from(this.schema).getChild(this.iid).getDataSchemaNode();
101
102         this.iid2 = YangInstanceIdentifier.builder()
103                 .node(baseQName)
104                 .build();
105         this.schemaNode2 = DataSchemaContextTree.from(this.schema).getChild(this.iid2).getDataSchemaNode();
106
107         this.iid3 = YangInstanceIdentifier.builder()
108                 .node(baseQName)
109                 .node(listQname)
110                 .node(nodeWithKey)
111                 .build();
112         this.schemaNode3 = DataSchemaContextTree.from(this.schema).getChild(this.iid3).getDataSchemaNode();
113
114         this.buildLeaf = Builders.leafBuilder()
115                 .withNodeIdentifier(new NodeIdentifier(leafQname))
116                 .withValue(0.2)
117                 .build();
118         final ContainerNode buildPlayerCont = Builders.containerBuilder()
119                 .withNodeIdentifier(new NodeIdentifier(containerQname))
120                 .withChild(this.buildLeaf)
121                 .build();
122         this.buildBaseCont = Builders.containerBuilder()
123                 .withNodeIdentifier(new NodeIdentifier(baseQName))
124                 .withChild(buildPlayerCont)
125                 .build();
126         final LeafNode<Object> content = Builders.leafBuilder()
127                 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
128                 .withValue("name of band")
129                 .build();
130         final LeafNode<Object> content2 = Builders.leafBuilder()
131                 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
132                 .withValue("band description")
133                 .build();
134         this.buildListEntry = Builders.mapEntryBuilder()
135                 .withNodeIdentifier(nodeWithKey)
136                 .withChild(content)
137                 .withChild(content2)
138                 .build();
139         final LeafNode<Object> content3 = Builders.leafBuilder()
140                 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "name")))
141                 .withValue("name of band 2")
142                 .build();
143         final LeafNode<Object> content4 = Builders.leafBuilder()
144                 .withNodeIdentifier(new NodeIdentifier(QName.create(baseQName, "description")))
145                 .withValue("band description 2")
146                 .build();
147         final MapEntryNode buildListEntry2 = Builders.mapEntryBuilder()
148                 .withNodeIdentifier(nodeWithKey2)
149                 .withChild(content3)
150                 .withChild(content4)
151                 .build();
152         final MapNode buildList = Builders.mapBuilder()
153                 .withNodeIdentifier(new NodeIdentifier(listQname))
154                 .withChild(this.buildListEntry)
155                 .withChild(buildListEntry2)
156                 .build();
157         this.buildBaseContWithList = Builders.containerBuilder()
158                 .withNodeIdentifier(new NodeIdentifier(baseQName))
159                 .withChild(buildList)
160                 .build();
161
162         Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
163         transactionChainHandler = new TransactionChainHandler(mockDataBroker);
164     }
165
166     @Test
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);
172     }
173
174     @Test
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);
180
181         iidContext = new InstanceIdentifierContext<>(this.iid2, this.schemaNode2, null, this.schema);
182         payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
183         PutDataTransactionUtil.validTopLevelNodeName(iidContext.getInstanceIdentifier(), payload);
184     }
185
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);
192     }
193
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);
200     }
201
202     @Test
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);
208     }
209
210     @Test
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);
215
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();
224
225         PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
226                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler), null,
227                 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());
232     }
233
234     @Test
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);
239
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();
248
249         PutDataTransactionUtil.putData(payload, this.refSchemaCtx,
250                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler), null,
251                 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());
256     }
257
258     @Test
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);
263
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,
274                 null);
275         verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
276         verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, this.iid2, payload.getData());
277     }
278 }