97f8b1fe23af70acce861638f7185e79011acd52
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / databind / jaxrs / QueryParamsTest.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.databind.jaxrs;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertSame;
15 import static org.junit.Assert.assertThrows;
16 import static org.junit.Assert.assertTrue;
17 import static org.mockito.Mockito.doReturn;
18
19 import java.util.List;
20 import java.util.Set;
21 import javax.ws.rs.core.MultivaluedHashMap;
22 import javax.ws.rs.core.MultivaluedMap;
23 import javax.ws.rs.core.UriInfo;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.Mock;
27 import org.mockito.junit.MockitoJUnitRunner;
28 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
29 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
30 import org.opendaylight.restconf.common.errors.RestconfError;
31 import org.opendaylight.restconf.nb.rfc8040.ContentParameter;
32 import org.opendaylight.restconf.nb.rfc8040.DepthParameter;
33 import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
34 import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
35 import org.opendaylight.yangtools.yang.common.ErrorTag;
36 import org.opendaylight.yangtools.yang.common.ErrorType;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
40 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
41
42 @RunWith(MockitoJUnitRunner.StrictStubs.class)
43 public class QueryParamsTest {
44     @Mock
45     public InstanceIdentifierContext<ContainerSchemaNode> context;
46     @Mock
47     public UriInfo uriInfo;
48     @Mock
49     public EffectiveModelContext modelContext;
50     @Mock
51     public ContainerSchemaNode containerSchema;
52     @Mock
53     public LeafSchemaNode containerChildSchema;
54
55     /**
56      * Test when parameter is present at most once.
57      */
58     @Test
59     public void getSingleParameterTest() {
60         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
61         parameters.putSingle(ContentParameter.uriName(), "all");
62         assertEquals("all", QueryParams.getSingleParameter(parameters, ContentParameter.uriName()));
63     }
64
65     /**
66      * Test when parameter is present more than once.
67      */
68     @Test
69     public void getSingleParameterNegativeTest() {
70         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
71         parameters.put(ContentParameter.uriName(), List.of("config", "nonconfig", "all"));
72
73         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
74             () -> QueryParams.getSingleParameter(parameters, ContentParameter.uriName()));
75         final List<RestconfError> errors = ex.getErrors();
76         assertEquals(1, errors.size());
77
78         final RestconfError error = errors.get(0);
79         assertEquals("Error type is not correct", ErrorType.PROTOCOL, error.getErrorType());
80         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, error.getErrorTag());
81     }
82
83     /**
84      * Test when all parameters are allowed.
85      */
86     @Test
87     public void checkParametersTypesTest() {
88         QueryParams.checkParametersTypes(Set.of("content"),
89             Set.of(ContentParameter.uriName(), DepthParameter.uriName()));
90     }
91
92     /**
93      * Test when not allowed parameter type is used.
94      */
95     @Test
96     public void checkParametersTypesNegativeTest() {
97         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
98             () -> QueryParams.checkParametersTypes(Set.of("not-allowed-parameter"),
99                 Set.of(ContentParameter.uriName(), DepthParameter.uriName())));
100         final List<RestconfError> errors = ex.getErrors();
101         assertEquals(1, errors.size());
102
103         final RestconfError error = errors.get(0);
104         assertEquals("Error type is not correct", ErrorType.PROTOCOL, error.getErrorType());
105         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, error.getErrorTag());
106     }
107
108     /**
109      * Test of parsing default parameters from URI request.
110      */
111     @Test
112     public void parseUriParametersDefaultTest() {
113         // no parameters, default values should be used
114         mockQueryParameters(new MultivaluedHashMap<String, String>());
115
116         final QueryParameters parsedParameters = QueryParams.newReadDataParams(context, uriInfo);
117
118         assertEquals(ContentParameter.ALL, parsedParameters.getContent());
119         assertNull(parsedParameters.getDepth());
120         assertNull(parsedParameters.getFields());
121     }
122
123     /**
124      * Testing parsing of with-defaults parameter which value which is not supported.
125      */
126     @Test
127     public void parseUriParametersWithDefaultInvalidTest() {
128         // preparation of input data
129         mockQueryParameter("with-defaults", "invalid");
130
131         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
132             () -> QueryParams.newReadDataParams(context, uriInfo));
133         final List<RestconfError> errors = ex.getErrors();
134         assertEquals(1, errors.size());
135         assertEquals(ErrorTag.INVALID_VALUE, errors.get(0).getErrorTag());
136     }
137
138     /**
139      * Negative test of parsing request URI parameters when depth parameter has not allowed value.
140      */
141     @Test
142     public void parseUriParametersDepthParameterNegativeTest() {
143         // inserted value is not allowed
144         mockQueryParameter("depth", "bounded");
145
146         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
147             () -> QueryParams.newReadDataParams(context, uriInfo));
148         // Bad request
149         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
150         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
151     }
152
153     /**
154      * Negative test of parsing request URI parameters when content parameter has not allowed value.
155      */
156     @Test
157     public void parseUriParametersContentParameterNegativeTest() {
158         mockQueryParameter("content", "not-allowed-parameter-value");
159
160         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
161             () -> QueryParams.newReadDataParams(context, uriInfo));
162         // Bad request
163         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
164         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
165     }
166
167     /**
168      * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
169      */
170     @Test
171     public void parseUriParametersDepthMaximalParameterNegativeTest() {
172         // inserted value is too high
173         mockQueryParameter("depth", "65536");
174
175         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
176             () -> QueryParams.newReadDataParams(context, uriInfo));
177         // Bad request
178         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
179         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
180     }
181
182     /**
183      * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
184      */
185     @Test
186     public void parseUriParametersDepthMinimalParameterNegativeTest() {
187         // inserted value is too low
188         mockQueryParameter("depth", "0");
189
190         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
191             () -> QueryParams.newReadDataParams(context, uriInfo));
192         // Bad request
193         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
194         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
195     }
196
197     /**
198      * Testing parsing of with-defaults parameter which value matches 'report-all-tagged' setting - default value should
199      * be set to {@code null} and tagged flag should be set to {@code true}.
200      */
201     @Test
202     public void parseUriParametersWithDefaultAndTaggedTest() {
203         // preparation of input data
204         mockQueryParameter("with-defaults", "report-all-tagged");
205
206         final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
207         assertNull(writerParameters.getWithDefault());
208         assertTrue(writerParameters.isTagged());
209     }
210
211     /**
212      * Testing parsing of with-defaults parameter which value matches 'report-all' setting - default value should
213      * be set to {@code null} and tagged flag should be set to {@code false}.
214      */
215     @Test
216     public void parseUriParametersWithDefaultAndReportAllTest() {
217         // preparation of input data
218         mockQueryParameter("with-defaults", "report-all");
219
220         final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
221         assertNull(writerParameters.getWithDefault());
222         assertFalse(writerParameters.isTagged());
223     }
224
225     /**
226      * Testing parsing of with-defaults parameter which value doesn't match report-all or report-all-tagged patterns
227      * - non-reporting setting.
228      */
229     @Test
230     public void parseUriParametersWithDefaultAndNonTaggedTest() {
231         // preparation of input data
232         mockQueryParameter("with-defaults", "explicit");
233
234         final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
235         assertSame(WithDefaultsParameter.EXPLICIT, writerParameters.getWithDefault());
236         assertFalse(writerParameters.isTagged());
237     }
238
239     /**
240      * Test of parsing user defined parameters from URI request.
241      */
242     @Test
243     public void parseUriParametersUserDefinedTest() {
244         final QName containerChild = QName.create("ns", "container-child");
245
246         final MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
247         parameters.putSingle("content", "config");
248         parameters.putSingle("depth", "10");
249         parameters.putSingle("fields", "container-child");
250         mockQueryParameters(parameters);
251
252         doReturn(QName.create(containerChild, "container")).when(containerSchema).getQName();
253         doReturn(containerChildSchema).when(containerSchema).dataChildByName(containerChild);
254         doReturn(containerChild).when(containerChildSchema).getQName();
255
256         doReturn(modelContext).when(context).getSchemaContext();
257         doReturn(containerSchema).when(context).getSchemaNode();
258
259         final QueryParameters parsedParameters = QueryParams.newReadDataParams(context, uriInfo);
260
261         // content
262         assertEquals(ContentParameter.CONFIG, parsedParameters.getContent());
263
264         // depth
265         final DepthParameter depth = parsedParameters.getDepth();
266         assertNotNull(depth);
267         assertEquals(10, depth.value());
268
269         // fields
270         assertNotNull(parsedParameters.getFields());
271         assertEquals(1, parsedParameters.getFields().size());
272         assertEquals(1, parsedParameters.getFields().get(0).size());
273         assertEquals(containerChild, parsedParameters.getFields().get(0).iterator().next());
274     }
275
276     private void mockQueryParameter(final String name, final String value) {
277         final MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
278         parameters.putSingle(name, value);
279         mockQueryParameters(parameters);
280     }
281
282     private void mockQueryParameters(final MultivaluedMap<String, String> parameters) {
283         doReturn(parameters).when(uriInfo).getQueryParameters();
284     }
285 }