Split Restconf implementations (draft02 and RFC) - tests
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / 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.nb.rfc8040.rests.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.nb.rfc8040.rests.transactions.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 =
91                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
92         assertEquals(DATA.data3, normalizedNode);
93     }
94
95     @Test
96     public void readAllHavingOnlyConfigTest() {
97         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
98                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
99         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
100                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
101         doReturn(DATA.path).when(context).getInstanceIdentifier();
102         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
103         final NormalizedNode<?, ?> normalizedNode =
104                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
105         assertEquals(DATA.data3, normalizedNode);
106     }
107
108     @Test
109     public void readAllHavingOnlyNonConfigTest() {
110         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
111                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
112         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
113                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
114         doReturn(DATA.path2).when(context).getInstanceIdentifier();
115         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
116         final NormalizedNode<?, ?> normalizedNode =
117                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
118         assertEquals(DATA.data2, normalizedNode);
119     }
120
121     @Test
122     public void readDataNonConfigTest() {
123         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
124                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
125         doReturn(DATA.path2).when(context).getInstanceIdentifier();
126         final String valueOfContent = RestconfDataServiceConstant.ReadData.NONCONFIG;
127         final NormalizedNode<?, ?> normalizedNode =
128                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
129         assertEquals(DATA.data2, normalizedNode);
130     }
131
132     @Test
133     public void readContainerDataAllTest() {
134         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
135                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
136         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
137                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
138         doReturn(DATA.path).when(context).getInstanceIdentifier();
139         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
140         final NormalizedNode<?, ?> normalizedNode =
141                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
142         final ContainerNode checkingData = Builders
143                 .containerBuilder()
144                 .withNodeIdentifier(NODE_IDENTIFIER)
145                 .withChild(DATA.contentLeaf)
146                 .withChild(DATA.contentLeaf2)
147                 .build();
148         assertEquals(checkingData, normalizedNode);
149     }
150
151     @Test
152     public void readContainerDataConfigNoValueOfContentTest() {
153         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
154                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
155         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
156                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
157         doReturn(DATA.path).when(context).getInstanceIdentifier();
158         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
159                 RestconfDataServiceConstant.ReadData.ALL, wrapper, schemaContext);
160         final ContainerNode checkingData = Builders
161                 .containerBuilder()
162                 .withNodeIdentifier(NODE_IDENTIFIER)
163                 .withChild(DATA.contentLeaf)
164                 .withChild(DATA.contentLeaf2)
165                 .build();
166         assertEquals(checkingData, normalizedNode);
167     }
168
169     @Test
170     public void readListDataAllTest() {
171         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData))).when(read)
172                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
173         doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData2))).when(read)
174                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
175         doReturn(DATA.path3).when(context).getInstanceIdentifier();
176         final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
177         final NormalizedNode<?, ?> normalizedNode =
178                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
179         final MapNode checkingData = Builders
180                 .mapBuilder()
181                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
182                 .withChild(DATA.checkData)
183                 .build();
184         assertEquals(checkingData, normalizedNode);
185     }
186
187     @Test
188     public void readDataWrongPathOrNoContentTest() {
189         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
190                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
191         doReturn(DATA.path2).when(context).getInstanceIdentifier();
192         final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
193         final NormalizedNode<?, ?> normalizedNode =
194                 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
195         assertNull(normalizedNode);
196     }
197
198     @Test(expected = RestconfDocumentedException.class)
199     public void readDataFailTest() {
200         final String valueOfContent = RestconfDataServiceConstant.ReadData.READ_TYPE_TX;
201         final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
202                 valueOfContent, wrapper, schemaContext);
203         assertNull(normalizedNode);
204     }
205
206     /**
207      * Test of parsing default parameters from URI request.
208      */
209     @Test
210     public void parseUriParametersDefaultTest() {
211         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
212         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
213
214         // no parameters, default values should be used
215         when(uriInfo.getQueryParameters()).thenReturn(parameters);
216
217         final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
218
219         assertEquals("Not correctly parsed URI parameter",
220                 RestconfDataServiceConstant.ReadData.ALL, parsedParameters.getContent());
221         assertNull("Not correctly parsed URI parameter",
222                 parsedParameters.getDepth());
223         assertNull("Not correctly parsed URI parameter",
224                 parsedParameters.getFields());
225     }
226
227     /**
228      * Test of parsing user defined parameters from URI request.
229      */
230     @Test
231     public void parseUriParametersUserDefinedTest() {
232         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
233         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
234
235         final String content = "config";
236         final String depth = "10";
237         final String fields = containerChildQName.getLocalName();
238
239         parameters.put("content", Collections.singletonList(content));
240         parameters.put("depth", Collections.singletonList(depth));
241         parameters.put("fields", Collections.singletonList(fields));
242
243         when(uriInfo.getQueryParameters()).thenReturn(parameters);
244
245         final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
246
247         // content
248         assertEquals("Not correctly parsed URI parameter",
249                 content, parsedParameters.getContent());
250
251         // depth
252         assertNotNull("Not correctly parsed URI parameter",
253                 parsedParameters.getDepth());
254         assertEquals("Not correctly parsed URI parameter",
255                 depth, parsedParameters.getDepth().toString());
256
257         // fields
258         assertNotNull("Not correctly parsed URI parameter",
259                 parsedParameters.getFields());
260         assertEquals("Not correctly parsed URI parameter",
261                 1, parsedParameters.getFields().size());
262         assertEquals("Not correctly parsed URI parameter",
263                 1, parsedParameters.getFields().get(0).size());
264         assertEquals("Not correctly parsed URI parameter",
265                 containerChildQName, parsedParameters.getFields().get(0).iterator().next());
266     }
267
268     /**
269      * Negative test of parsing request URI parameters when content parameter has not allowed value.
270      */
271     @Test
272     public void parseUriParametersContentParameterNegativeTest() {
273         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
274         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
275
276         parameters.put("content", Collections.singletonList("not-allowed-parameter-value"));
277         when(uriInfo.getQueryParameters()).thenReturn(parameters);
278
279         try {
280             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
281             fail("Test expected to fail due to not allowed parameter value");
282         } catch (final RestconfDocumentedException e) {
283             // Bad request
284             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
285             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
286             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
287         }
288     }
289
290     /**
291      * Negative test of parsing request URI parameters when depth parameter has not allowed value.
292      */
293     @Test
294     public void parseUriParametersDepthParameterNegativeTest() {
295         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
296         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
297
298         // inserted value is not allowed
299         parameters.put("depth", Collections.singletonList("bounded"));
300         when(uriInfo.getQueryParameters()).thenReturn(parameters);
301
302         try {
303             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
304             fail("Test expected to fail due to not allowed parameter value");
305         } catch (final RestconfDocumentedException e) {
306             // Bad request
307             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
308             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
309             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
310         }
311     }
312
313     /**
314      * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
315      */
316     @Test
317     public void parseUriParametersDepthMinimalParameterNegativeTest() {
318         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
319         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
320
321         // inserted value is too low
322         parameters.put(
323                 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MIN_DEPTH - 1)));
324         when(uriInfo.getQueryParameters()).thenReturn(parameters);
325
326         try {
327             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
328             fail("Test expected to fail due to not allowed parameter value");
329         } catch (final RestconfDocumentedException e) {
330             // Bad request
331             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
332             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
333             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
334         }
335     }
336
337     /**
338      * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
339      */
340     @Test
341     public void parseUriParametersDepthMaximalParameterNegativeTest() {
342         final UriInfo uriInfo = Mockito.mock(UriInfo.class);
343         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
344
345         // inserted value is too high
346         parameters.put(
347                 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MAX_DEPTH + 1)));
348         when(uriInfo.getQueryParameters()).thenReturn(parameters);
349
350         try {
351             ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
352             fail("Test expected to fail due to not allowed parameter value");
353         } catch (final RestconfDocumentedException e) {
354             // Bad request
355             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
356             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
357             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
358         }
359     }
360 }