45b216420e93e297e9eb41a37eaa419ee40d6fdb
[netconf.git] / restconf / restconf-nb-bierman02 / src / test / java / org / opendaylight / restconf / restful / utils / ReadDataTransactionUtilTest.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.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.fail;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.when;
17
18 import com.google.common.base.Optional;
19 import com.google.common.util.concurrent.Futures;
20 import java.util.Collections;
21 import javax.ws.rs.core.MultivaluedHashMap;
22 import javax.ws.rs.core.UriInfo;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.mockito.Mock;
26 import org.mockito.Mockito;
27 import org.mockito.MockitoAnnotations;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
31 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
32 import org.opendaylight.restconf.common.context.WriterParameters;
33 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
34 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
35 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
36 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
46
47 public class ReadDataTransactionUtilTest {
48
49     private static final TestData DATA = new TestData();
50     private static final YangInstanceIdentifier.NodeIdentifier NODE_IDENTIFIER = new YangInstanceIdentifier
51             .NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
52
53     private TransactionVarsWrapper wrapper;
54     @Mock
55     private DOMTransactionChain transactionChain;
56     @Mock
57     private InstanceIdentifierContext<ContainerSchemaNode> context;
58     @Mock
59     private DOMDataReadOnlyTransaction read;
60     @Mock
61     private SchemaContext schemaContext;
62     @Mock
63     private ContainerSchemaNode containerSchemaNode;
64     @Mock
65     private LeafSchemaNode containerChildNode;
66     private QName containerChildQName;
67
68     @Before
69     public void setUp() {
70         MockitoAnnotations.initMocks(this);
71
72         containerChildQName = QName.create("ns", "2016-02-28", "container-child");
73
74         when(transactionChain.newReadOnlyTransaction()).thenReturn(read);
75         when(context.getSchemaContext()).thenReturn(schemaContext);
76         when(context.getSchemaNode()).thenReturn(containerSchemaNode);
77         when(containerSchemaNode.getQName()).thenReturn(NODE_IDENTIFIER.getNodeType());
78         when(containerChildNode.getQName()).thenReturn(containerChildQName);
79         when(containerSchemaNode.getDataChildByName(containerChildQName)).thenReturn(containerChildNode);
80
81         wrapper = new TransactionVarsWrapper(this.context, null, this.transactionChain);
82     }
83
84     @Test
85     public void readDataConfigTest() {
86         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
87                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
88         doReturn(DATA.path).when(context).getInstanceIdentifier();
89         final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
90         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
91         assertEquals(DATA.data3, normalizedNode);
92     }
93
94     @Test
95     public void readAllHavingOnlyConfigTest() {
96         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
97                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
98         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
99                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
100         doReturn(DATA.path).when(context).getInstanceIdentifier();
101         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
102         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
103         assertEquals(DATA.data3, normalizedNode);
104     }
105
106     @Test
107     public void readAllHavingOnlyNonConfigTest() {
108         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
109                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
110         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
111                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
112         doReturn(DATA.path2).when(context).getInstanceIdentifier();
113         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
114         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
115         assertEquals(DATA.data2, normalizedNode);
116     }
117
118     @Test
119     public void readDataNonConfigTest() {
120         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
121                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
122         doReturn(DATA.path2).when(context).getInstanceIdentifier();
123         final String valueOfContent = RestconfDataServiceConstant.ReadData.NONCONFIG;
124         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
125         assertEquals(DATA.data2, normalizedNode);
126     }
127
128     @Test
129     public void readContainerDataAllTest() {
130         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
131                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
132         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
133                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
134         doReturn(DATA.path).when(context).getInstanceIdentifier();
135         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
136         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
137         final ContainerNode checkingData = Builders
138                 .containerBuilder()
139                 .withNodeIdentifier(NODE_IDENTIFIER)
140                 .withChild(DATA.contentLeaf)
141                 .withChild(DATA.contentLeaf2)
142                 .build();
143         assertEquals(checkingData, normalizedNode);
144     }
145
146     @Test
147     public void readContainerDataConfigNoValueOfContentTest() {
148         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
149                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
150         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
151                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
152         doReturn(DATA.path).when(context).getInstanceIdentifier();
153         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
154                 RestconfDataServiceConstant.ReadData.ALL, wrapper);
155         final ContainerNode checkingData = Builders
156                 .containerBuilder()
157                 .withNodeIdentifier(NODE_IDENTIFIER)
158                 .withChild(DATA.contentLeaf)
159                 .withChild(DATA.contentLeaf2)
160                 .build();
161         assertEquals(checkingData, normalizedNode);
162     }
163
164     @Test
165     public void readListDataAllTest() {
166         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData))).when(read)
167                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
168         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData2))).when(read)
169                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
170         doReturn(DATA.path3).when(context).getInstanceIdentifier();
171         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
172         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
173         final MapNode checkingData = Builders
174                 .mapBuilder()
175                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
176                 .withChild(DATA.checkData)
177                 .build();
178         assertEquals(checkingData, normalizedNode);
179     }
180
181     @Test
182     public void readDataWrongPathOrNoContentTest() {
183         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
184                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
185         doReturn(DATA.path2).when(context).getInstanceIdentifier();
186         final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
187         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
188         assertNull(normalizedNode);
189     }
190
191     @Test(expected = RestconfDocumentedException.class)
192     public void readDataFailTest() {
193         final String valueOfContent = RestconfDataServiceConstant.ReadData.READ_TYPE_TX;
194         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
195                 valueOfContent, wrapper);
196         assertNull(normalizedNode);
197     }
198
199     /**
200      * Test of parsing default parameters from URI request.
201      */
202     @Test
203     public void parseUriParametersDefaultTest() {
204         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
205         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
206
207         // no parameters, default values should be used
208         when(uriInfo.getQueryParameters()).thenReturn(parameters);
209
210         final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
211
212         assertEquals("Not correctly parsed URI parameter",
213                 RestconfDataServiceConstant.ReadData.ALL, parsedParameters.getContent());
214         assertNull("Not correctly parsed URI parameter",
215                 parsedParameters.getDepth());
216         assertNull("Not correctly parsed URI parameter",
217                 parsedParameters.getFields());
218     }
219
220     /**
221      * Test of parsing user defined parameters from URI request.
222      */
223     @Test
224     public void parseUriParametersUserDefinedTest() {
225         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
226         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
227
228         final String content = "config";
229         final String depth = "10";
230         final String fields = containerChildQName.getLocalName();
231
232         parameters.put("content", Collections.singletonList(content));
233         parameters.put("depth", Collections.singletonList(depth));
234         parameters.put("fields", Collections.singletonList(fields));
235
236         when(uriInfo.getQueryParameters()).thenReturn(parameters);
237
238         final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
239
240         // content
241         assertEquals("Not correctly parsed URI parameter",
242                 content, parsedParameters.getContent());
243
244         // depth
245         assertNotNull("Not correctly parsed URI parameter",
246                 parsedParameters.getDepth());
247         assertEquals("Not correctly parsed URI parameter",
248                 depth, parsedParameters.getDepth().toString());
249
250         // fields
251         assertNotNull("Not correctly parsed URI parameter",
252                 parsedParameters.getFields());
253         assertEquals("Not correctly parsed URI parameter",
254                 1, parsedParameters.getFields().size());
255         assertEquals("Not correctly parsed URI parameter",
256                 1, parsedParameters.getFields().get(0).size());
257         assertEquals("Not correctly parsed URI parameter",
258                 containerChildQName, parsedParameters.getFields().get(0).iterator().next());
259     }
260
261     /**
262      * Negative test of parsing request URI parameters when content parameter has not allowed value.
263      */
264     @Test
265     public void parseUriParametersContentParameterNegativeTest() {
266         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
267         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
268
269         parameters.put("content", Collections.singletonList("not-allowed-parameter-value"));
270         when(uriInfo.getQueryParameters()).thenReturn(parameters);
271
272         try {
273             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
274             fail("Test expected to fail due to not allowed parameter value");
275         } catch (final RestconfDocumentedException e) {
276             // Bad request
277             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
278             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
279             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
280         }
281     }
282
283     /**
284      * Negative test of parsing request URI parameters when depth parameter has not allowed value.
285      */
286     @Test
287     public void parseUriParametersDepthParameterNegativeTest() {
288         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
289         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
290
291         // inserted value is not allowed
292         parameters.put("depth", Collections.singletonList("bounded"));
293         when(uriInfo.getQueryParameters()).thenReturn(parameters);
294
295         try {
296             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
297             fail("Test expected to fail due to not allowed parameter value");
298         } catch (final RestconfDocumentedException e) {
299             // Bad request
300             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
301             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
302             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
303         }
304     }
305
306     /**
307      * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
308      */
309     @Test
310     public void parseUriParametersDepthMinimalParameterNegativeTest() {
311         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
312         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
313
314         // inserted value is too low
315         parameters.put(
316                 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MIN_DEPTH - 1)));
317         when(uriInfo.getQueryParameters()).thenReturn(parameters);
318
319         try {
320             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
321             fail("Test expected to fail due to not allowed parameter value");
322         } catch (final RestconfDocumentedException e) {
323             // Bad request
324             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
325             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
326             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
327         }
328     }
329
330     /**
331      * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
332      */
333     @Test
334     public void parseUriParametersDepthMaximalParameterNegativeTest() {
335         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
336         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
337
338         // inserted value is too high
339         parameters.put(
340                 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MAX_DEPTH + 1)));
341         when(uriInfo.getQueryParameters()).thenReturn(parameters);
342
343         try {
344             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
345             fail("Test expected to fail due to not allowed parameter value");
346         } catch (final RestconfDocumentedException e) {
347             // Bad request
348             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
349             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
350             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
351         }
352     }
353 }