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