2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.restconf.nb.rfc8040.databind.jaxrs;
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.assertThrows;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
19 import java.util.List;
21 import java.util.function.Function;
22 import javax.ws.rs.core.MultivaluedHashMap;
23 import javax.ws.rs.core.MultivaluedMap;
24 import javax.ws.rs.core.UriInfo;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
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.InsertParam;
34 import org.opendaylight.restconf.nb.rfc8040.RestconfQueryParam;
35 import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParam;
36 import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
37 import org.opendaylight.yangtools.yang.common.ErrorTag;
38 import org.opendaylight.yangtools.yang.common.ErrorType;
39 import org.opendaylight.yangtools.yang.common.QName;
40 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
42 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
44 @RunWith(MockitoJUnitRunner.StrictStubs.class)
45 public class QueryParamsTest {
47 * Test when parameter is present at most once.
50 public void optionalParamTest() {
51 assertEquals("all", QueryParams.optionalParam(ContentParam.uriName, List.of("all")));
55 * Test when parameter is present more than once.
58 public void optionalParamMultipleTest() {
59 final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
60 () -> QueryParams.optionalParam(ContentParam.uriName, List.of("config", "nonconfig", "all")));
61 final List<RestconfError> errors = ex.getErrors();
62 assertEquals(1, errors.size());
64 final RestconfError error = errors.get(0);
65 assertEquals("Error type is not correct", ErrorType.PROTOCOL, error.getErrorType());
66 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, error.getErrorTag());
70 * Test when not allowed parameter type is used.
73 public void checkParametersTypesNegativeTest() {
74 assertUnknownParam(QueryParams::newNotificationQueryParams);
75 assertUnknownParam(QueryParams::newReadDataParams);
76 assertUnknownParam(QueryParams::newWriteDataParams);
78 assertInvalidParam(QueryParams::newNotificationQueryParams, ContentParam.ALL);
79 assertInvalidParam(QueryParams::newReadDataParams, InsertParam.LAST);
80 assertInvalidParam(QueryParams::newWriteDataParams, ContentParam.ALL);
84 * Test of parsing default parameters from URI request.
87 public void parseUriParametersDefaultTest() {
88 // no parameters, default values should be used
89 final var params = assertParams(QueryParams::newReadDataParams, new MultivaluedHashMap<String, String>());
90 assertEquals(ContentParam.ALL, params.content());
91 assertNull(params.depth());
92 assertNull(params.fields());
96 public void testInvalidValueReadDataParams() {
97 assertInvalidValue(QueryParams::newReadDataParams, ContentParam.uriName);
98 assertInvalidValue(QueryParams::newReadDataParams, DepthParam.uriName);
99 assertInvalidValue(QueryParams::newReadDataParams, WithDefaultsParam.uriName);
101 // inserted value is too high
102 assertInvalidValue(QueryParams::newReadDataParams, DepthParam.uriName, "65536");
103 // inserted value is too low
104 assertInvalidValue(QueryParams::newReadDataParams, DepthParam.uriName, "0");
108 * Testing parsing of with-defaults parameter which value matches 'report-all-tagged' setting - default value should
109 * be set to {@code null} and tagged flag should be set to {@code true}.
112 public void parseUriParametersWithDefaultAndTaggedTest() {
113 final var params = assertParams(QueryParams::newReadDataParams, WithDefaultsParam.uriName, "report-all-tagged");
114 assertNull(params.withDefaults());
115 assertTrue(params.tagged());
119 * Testing parsing of with-defaults parameter which value matches 'report-all' setting - default value should
120 * be set to {@code null} and tagged flag should be set to {@code false}.
123 public void parseUriParametersWithDefaultAndReportAllTest() {
124 final var params = assertParams(QueryParams::newReadDataParams, WithDefaultsParam.uriName, "report-all");
125 assertNull(params.withDefaults());
126 assertFalse(params.tagged());
130 * Testing parsing of with-defaults parameter which value doesn't match report-all or report-all-tagged patterns
131 * - non-reporting setting.
134 public void parseUriParametersWithDefaultAndNonTaggedTest() {
135 final var params = assertParams(QueryParams::newReadDataParams, WithDefaultsParam.uriName, "explicit");
136 assertEquals(WithDefaultsParam.EXPLICIT, params.withDefaults());
137 assertFalse(params.tagged());
141 * Test of parsing user defined parameters from URI request.
144 public void parseUriParametersUserDefinedTest() {
145 final QName containerChild = QName.create("ns", "container-child");
147 final var parameters = new MultivaluedHashMap<String, String>();
148 parameters.putSingle("content", "config");
149 parameters.putSingle("depth", "10");
150 parameters.putSingle("fields", "container-child");
152 final var params = assertParams(QueryParams::newReadDataParams, parameters);
154 assertEquals(ContentParam.CONFIG, params.content());
157 final DepthParam depth = params.depth();
158 assertNotNull(depth);
159 assertEquals(10, depth.value());
162 assertNotNull(params.fields());
164 // fields for write filtering
165 final var containerSchema = mock(ContainerSchemaNode.class);
166 doReturn(QName.create(containerChild, "container")).when(containerSchema).getQName();
167 final var containerChildSchema = mock(LeafSchemaNode.class);
168 doReturn(containerChild).when(containerChildSchema).getQName();
169 doReturn(containerChildSchema).when(containerSchema).dataChildByName(containerChild);
170 final var context = mock(InstanceIdentifierContext.class);
171 final var modelContext = mock(EffectiveModelContext.class);
172 doReturn(modelContext).when(context).getSchemaContext();
173 doReturn(containerSchema).when(context).getSchemaNode();
175 final QueryParameters queryParameters = QueryParams.newQueryParameters(params, context);
176 final List<Set<QName>> fields = queryParameters.fields();
177 assertNotNull(fields);
178 assertEquals(1, fields.size());
179 assertEquals(Set.of(containerChild), fields.get(0));
182 private static void assertInvalidParam(final Function<UriInfo, ?> paramsMethod, final RestconfQueryParam<?> param) {
183 final var params = new MultivaluedHashMap<String, String>();
184 params.putSingle(param.paramName(), "odl-test-value");
185 assertParamsThrows(ErrorTag.MALFORMED_MESSAGE, paramsMethod, params);
188 private static void assertUnknownParam(final Function<UriInfo, ?> paramsMethod) {
189 final var params = new MultivaluedHashMap<String, String>();
190 params.putSingle("odl-unknown-param", "odl-test-value");
191 assertParamsThrows(ErrorTag.UNKNOWN_ATTRIBUTE, paramsMethod, params);
194 private static void assertInvalidValue(final Function<UriInfo, ?> paramsMethod, final String name) {
195 assertInvalidValue(paramsMethod, name, "odl-invalid-value");
198 private static void assertInvalidValue(final Function<UriInfo, ?> paramsMethod, final String name,
199 final String value) {
200 final var params = new MultivaluedHashMap<String, String>();
201 params.putSingle(name, value);
202 assertParamsThrows(ErrorTag.INVALID_VALUE, paramsMethod, params);
205 private static void assertParamsThrows(final ErrorTag expectedTag, final Function<UriInfo, ?> paramsMethod,
206 final MultivaluedMap<String, String> params) {
207 final var uriInfo = mock(UriInfo.class);
208 doReturn(params).when(uriInfo).getQueryParameters();
210 final var ex = assertThrows(RestconfDocumentedException.class, () -> paramsMethod.apply(uriInfo));
211 final var errors = ex.getErrors();
212 assertEquals(1, errors.size());
214 final var error = errors.get(0);
215 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
216 assertEquals(expectedTag, error.getErrorTag());
219 private static <T> T assertParams(final Function<UriInfo, T> paramsMethod, final String name,
220 final String value) {
221 final var params = new MultivaluedHashMap<String, String>();
222 params.putSingle(name, value);
223 return assertParams(paramsMethod, params);
226 private static <T> T assertParams(final Function<UriInfo, T> paramsMethod,
227 final MultivaluedMap<String, String> params) {
228 final var uriInfo = mock(UriInfo.class);
229 doReturn(params).when(uriInfo).getQueryParameters();
230 return paramsMethod.apply(uriInfo);