Rework query parameter parsing
[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 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
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 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.when;
20 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
21
22 import com.google.common.collect.ImmutableList;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.Set;
26 import javax.ws.rs.core.MultivaluedHashMap;
27 import javax.ws.rs.core.UriInfo;
28 import org.eclipse.jdt.annotation.NonNull;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.mockito.Mock;
34 import org.mockito.junit.MockitoJUnitRunner;
35 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
36 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
37 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
38 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
39 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
40 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
41 import org.opendaylight.restconf.common.errors.RestconfError;
42 import org.opendaylight.restconf.nb.rfc8040.ContentParameter;
43 import org.opendaylight.restconf.nb.rfc8040.DepthParameter;
44 import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
45 import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
46 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
47 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
48 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
49 import org.opendaylight.yangtools.yang.common.ErrorTag;
50 import org.opendaylight.yangtools.yang.common.ErrorType;
51 import org.opendaylight.yangtools.yang.common.QName;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
54 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
56 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
57 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
59 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
60 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
61 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
62 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
63 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
64
65 @RunWith(MockitoJUnitRunner.StrictStubs.class)
66 public class ReadDataTransactionUtilTest {
67
68     private static final TestData DATA = new TestData();
69     private static final NodeIdentifier NODE_IDENTIFIER =
70         new NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
71
72     private RestconfStrategy mdsalStrategy;
73     private RestconfStrategy netconfStrategy;
74     @Mock
75     private NetconfDataTreeService netconfService;
76     @Mock
77     private InstanceIdentifierContext<ContainerSchemaNode> context;
78     @Mock
79     private DOMDataTreeReadTransaction read;
80     @Mock
81     private EffectiveModelContext schemaContext;
82     @Mock
83     private ContainerSchemaNode containerSchemaNode;
84     @Mock
85     private LeafSchemaNode containerChildNode;
86     private QName containerChildQName;
87
88     @Before
89     public void setUp() {
90         containerChildQName = QName.create("ns", "2016-02-28", "container-child");
91
92         when(context.getSchemaContext()).thenReturn(schemaContext);
93         when(context.getSchemaNode()).thenReturn(containerSchemaNode);
94         when(containerSchemaNode.getQName()).thenReturn(NODE_IDENTIFIER.getNodeType());
95         when(containerChildNode.getQName()).thenReturn(containerChildQName);
96         when(containerSchemaNode.dataChildByName(containerChildQName)).thenReturn(containerChildNode);
97
98         DOMDataBroker mockDataBroker = mock(DOMDataBroker.class);
99         doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
100         mdsalStrategy = new MdsalRestconfStrategy(mockDataBroker);
101         netconfStrategy = new NetconfRestconfStrategy(netconfService);
102     }
103
104     @Test
105     public void readDataConfigTest() {
106         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(read)
107                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
108         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
109         NormalizedNode normalizedNode = readData(ContentParameter.CONFIG, DATA.path, mdsalStrategy);
110         assertEquals(DATA.data3, normalizedNode);
111
112         normalizedNode = readData(ContentParameter.CONFIG, DATA.path, netconfStrategy);
113         assertEquals(DATA.data3, normalizedNode);
114     }
115
116     @Test
117     public void readAllHavingOnlyConfigTest() {
118         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(read)
119                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
120         doReturn(immediateFluentFuture(Optional.empty())).when(read)
121                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
122         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
123         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(DATA.path);
124         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
125         assertEquals(DATA.data3, normalizedNode);
126
127         normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
128         assertEquals(DATA.data3, normalizedNode);
129     }
130
131     @Test
132     public void readAllHavingOnlyNonConfigTest() {
133         doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(read)
134                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
135         doReturn(immediateFluentFuture(Optional.empty())).when(read)
136                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
137         doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(netconfService).get(DATA.path2);
138         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(DATA.path2);
139         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path2, mdsalStrategy);
140         assertEquals(DATA.data2, normalizedNode);
141
142         normalizedNode = readData(ContentParameter.ALL, DATA.path2, netconfStrategy);
143         assertEquals(DATA.data2, normalizedNode);
144     }
145
146     @Test
147     public void readDataNonConfigTest() {
148         doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(read)
149                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
150         doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(netconfService).get(DATA.path2);
151         NormalizedNode normalizedNode = readData(ContentParameter.NONCONFIG, DATA.path2, mdsalStrategy);
152         assertEquals(DATA.data2, normalizedNode);
153
154         normalizedNode = readData(ContentParameter.NONCONFIG, DATA.path2, netconfStrategy);
155         assertEquals(DATA.data2, normalizedNode);
156     }
157
158     @Test
159     public void readContainerDataAllTest() {
160         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(read)
161                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
162         doReturn(immediateFluentFuture(Optional.of(DATA.data4))).when(read)
163                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
164         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
165         doReturn(immediateFluentFuture(Optional.of(DATA.data4))).when(netconfService).get(DATA.path);
166         final ContainerNode checkingData = Builders
167                 .containerBuilder()
168                 .withNodeIdentifier(NODE_IDENTIFIER)
169                 .withChild(DATA.contentLeaf)
170                 .withChild(DATA.contentLeaf2)
171                 .build();
172         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
173         assertEquals(checkingData, normalizedNode);
174
175         normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
176         assertEquals(checkingData, normalizedNode);
177     }
178
179     @Test
180     public void readContainerDataConfigNoValueOfContentTest() {
181         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(read)
182                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
183         doReturn(immediateFluentFuture(Optional.of(DATA.data4))).when(read)
184                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
185         doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
186         doReturn(immediateFluentFuture(Optional.of(DATA.data4))).when(netconfService).get(DATA.path);
187         final ContainerNode checkingData = Builders
188                 .containerBuilder()
189                 .withNodeIdentifier(NODE_IDENTIFIER)
190                 .withChild(DATA.contentLeaf)
191                 .withChild(DATA.contentLeaf2)
192                 .build();
193         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
194         assertEquals(checkingData, normalizedNode);
195
196         normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
197         assertEquals(checkingData, normalizedNode);
198     }
199
200     @Test
201     public void readListDataAllTest() {
202         doReturn(immediateFluentFuture(Optional.of(DATA.listData))).when(read)
203                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
204         doReturn(immediateFluentFuture(Optional.of(DATA.listData2))).when(read)
205                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
206         doReturn(immediateFluentFuture(Optional.of(DATA.listData))).when(netconfService).get(DATA.path3);
207         doReturn(immediateFluentFuture(Optional.of(DATA.listData2))).when(netconfService).getConfig(DATA.path3);
208         final MapNode checkingData = Builders
209                 .mapBuilder()
210                 .withNodeIdentifier(new NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
211                 .withChild(DATA.checkData)
212                 .build();
213         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3, mdsalStrategy);
214         assertEquals(checkingData, normalizedNode);
215
216         normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
217         assertEquals(checkingData, normalizedNode);
218     }
219
220     @Test
221     public void readOrderedListDataAllTest() {
222         doReturn(immediateFluentFuture(Optional.of(DATA.orderedMapNode1))).when(read)
223                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
224         doReturn(immediateFluentFuture(Optional.of(DATA.orderedMapNode2))).when(read)
225                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
226         doReturn(immediateFluentFuture(Optional.of(DATA.orderedMapNode1))).when(netconfService).get(DATA.path3);
227         doReturn(immediateFluentFuture(Optional.of(DATA.orderedMapNode2))).when(netconfService)
228                 .getConfig(DATA.path3);
229         final MapNode expectedData = Builders.orderedMapBuilder()
230                 .withNodeIdentifier(new NodeIdentifier(DATA.listQname))
231                 .withChild(DATA.checkData)
232                 .build();
233         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3,
234                 mdsalStrategy);
235         assertEquals(expectedData, normalizedNode);
236
237         normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
238         assertEquals(expectedData, normalizedNode);
239     }
240
241     @Test
242     public void readUnkeyedListDataAllTest() {
243         doReturn(immediateFluentFuture(Optional.of(DATA.unkeyedListNode1))).when(read)
244                 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
245         doReturn(immediateFluentFuture(Optional.of(DATA.unkeyedListNode2))).when(read)
246                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
247         doReturn(immediateFluentFuture(Optional.of(DATA.unkeyedListNode1))).when(netconfService).get(DATA.path3);
248         doReturn(immediateFluentFuture(Optional.of(DATA.unkeyedListNode2))).when(netconfService)
249                 .getConfig(DATA.path3);
250         final UnkeyedListNode expectedData = Builders.unkeyedListBuilder()
251                 .withNodeIdentifier(new NodeIdentifier(DATA.listQname))
252                 .withChild(Builders.unkeyedListEntryBuilder()
253                         .withNodeIdentifier(new NodeIdentifier(DATA.listQname))
254                         .withChild(DATA.unkeyedListEntryNode1.body().iterator().next())
255                         .withChild(DATA.unkeyedListEntryNode2.body().iterator().next()).build()).build();
256         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3, mdsalStrategy);
257         assertEquals(expectedData, normalizedNode);
258
259         normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
260         assertEquals(expectedData, normalizedNode);
261     }
262
263     @Test
264     public void readLeafListDataAllTest() {
265         doReturn(immediateFluentFuture(Optional.of(DATA.leafSetNode1))).when(read)
266                 .read(LogicalDatastoreType.OPERATIONAL, DATA.leafSetNodePath);
267         doReturn(immediateFluentFuture(Optional.of(DATA.leafSetNode2))).when(read)
268                 .read(LogicalDatastoreType.CONFIGURATION, DATA.leafSetNodePath);
269         doReturn(immediateFluentFuture(Optional.of(DATA.leafSetNode1))).when(netconfService)
270                 .get(DATA.leafSetNodePath);
271         doReturn(immediateFluentFuture(Optional.of(DATA.leafSetNode2))).when(netconfService)
272                 .getConfig(DATA.leafSetNodePath);
273         final LeafSetNode<String> expectedData = Builders.<String>leafSetBuilder()
274                 .withNodeIdentifier(new NodeIdentifier(DATA.leafListQname))
275                 .withValue(ImmutableList.<LeafSetEntryNode<String>>builder()
276                         .addAll(DATA.leafSetNode1.body())
277                         .addAll(DATA.leafSetNode2.body())
278                         .build())
279                 .build();
280         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath,
281                 mdsalStrategy);
282         assertEquals(expectedData, normalizedNode);
283
284         normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath, netconfStrategy);
285         assertEquals(expectedData, normalizedNode);
286     }
287
288     @Test
289     public void readOrderedLeafListDataAllTest() {
290         doReturn(immediateFluentFuture(Optional.of(DATA.orderedLeafSetNode1))).when(read)
291                 .read(LogicalDatastoreType.OPERATIONAL, DATA.leafSetNodePath);
292         doReturn(immediateFluentFuture(Optional.of(DATA.orderedLeafSetNode2))).when(read)
293                 .read(LogicalDatastoreType.CONFIGURATION, DATA.leafSetNodePath);
294         doReturn(immediateFluentFuture(Optional.of(DATA.orderedLeafSetNode1))).when(netconfService)
295                 .get(DATA.leafSetNodePath);
296         doReturn(immediateFluentFuture(Optional.of(DATA.orderedLeafSetNode2))).when(netconfService)
297                 .getConfig(DATA.leafSetNodePath);
298         final LeafSetNode<String> expectedData = Builders.<String>orderedLeafSetBuilder()
299                 .withNodeIdentifier(new NodeIdentifier(DATA.leafListQname))
300                 .withValue(ImmutableList.<LeafSetEntryNode<String>>builder()
301                         .addAll(DATA.orderedLeafSetNode1.body())
302                         .addAll(DATA.orderedLeafSetNode2.body())
303                         .build())
304                 .build();
305         NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath,
306                 mdsalStrategy);
307         assertEquals(expectedData, normalizedNode);
308
309         normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath, netconfStrategy);
310         assertEquals(expectedData, normalizedNode);
311     }
312
313     @Test
314     public void readDataWrongPathOrNoContentTest() {
315         doReturn(immediateFluentFuture(Optional.empty())).when(read)
316                 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
317         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(DATA.path2);
318         NormalizedNode normalizedNode = readData(ContentParameter.CONFIG, DATA.path2, mdsalStrategy);
319         assertNull(normalizedNode);
320
321         normalizedNode = readData(ContentParameter.CONFIG, DATA.path2, netconfStrategy);
322         assertNull(normalizedNode);
323     }
324
325     /**
326      * Test of parsing default parameters from URI request.
327      */
328     @Test
329     public void parseUriParametersDefaultTest() {
330         final UriInfo uriInfo = mock(UriInfo.class);
331         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
332
333         // no parameters, default values should be used
334         when(uriInfo.getQueryParameters()).thenReturn(parameters);
335
336         final QueryParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
337
338         assertEquals(ContentParameter.ALL, parsedParameters.getContent());
339         assertNull(parsedParameters.getDepth());
340         assertNull(parsedParameters.getFields());
341     }
342
343     /**
344      * Test of parsing user defined parameters from URI request.
345      */
346     @Test
347     public void parseUriParametersUserDefinedTest() {
348         final UriInfo uriInfo = mock(UriInfo.class);
349         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
350         parameters.putSingle("content", "config");
351         parameters.putSingle("depth", "10");
352         parameters.putSingle("fields", containerChildQName.getLocalName());
353
354         when(uriInfo.getQueryParameters()).thenReturn(parameters);
355
356         final QueryParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
357
358         // content
359         assertEquals(ContentParameter.CONFIG, parsedParameters.getContent());
360
361         // depth
362         final DepthParameter depth = parsedParameters.getDepth();
363         assertNotNull(depth);
364         assertEquals(10, depth.value());
365
366         // fields
367         assertNotNull(parsedParameters.getFields());
368         assertEquals(1, parsedParameters.getFields().size());
369         assertEquals(1, parsedParameters.getFields().get(0).size());
370         assertEquals(containerChildQName, parsedParameters.getFields().get(0).iterator().next());
371     }
372
373     /**
374      * Negative test of parsing request URI parameters when content parameter has not allowed value.
375      */
376     @Test
377     public void parseUriParametersContentParameterNegativeTest() {
378         final UriInfo uriInfo = mock(UriInfo.class);
379         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
380         parameters.putSingle("content", "not-allowed-parameter-value");
381         when(uriInfo.getQueryParameters()).thenReturn(parameters);
382
383         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
384             () -> ReadDataTransactionUtil.parseUriParameters(context, uriInfo));
385         // Bad request
386         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
387         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
388     }
389
390     /**
391      * Negative test of parsing request URI parameters when depth parameter has not allowed value.
392      */
393     @Test
394     public void parseUriParametersDepthParameterNegativeTest() {
395         final UriInfo uriInfo = mock(UriInfo.class);
396         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
397
398         // inserted value is not allowed
399         parameters.putSingle("depth", "bounded");
400         when(uriInfo.getQueryParameters()).thenReturn(parameters);
401
402         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
403             () -> ReadDataTransactionUtil.parseUriParameters(context, uriInfo));
404         // Bad request
405         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
406         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
407     }
408
409     /**
410      * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
411      */
412     @Test
413     public void parseUriParametersDepthMinimalParameterNegativeTest() {
414         final UriInfo uriInfo = mock(UriInfo.class);
415         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
416
417         // inserted value is too low
418         parameters.putSingle("depth", "0");
419         when(uriInfo.getQueryParameters()).thenReturn(parameters);
420
421         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
422             () -> ReadDataTransactionUtil.parseUriParameters(context, uriInfo));
423         // Bad request
424         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
425         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
426     }
427
428     /**
429      * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
430      */
431     @Test
432     public void parseUriParametersDepthMaximalParameterNegativeTest() {
433         final UriInfo uriInfo = mock(UriInfo.class);
434         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
435
436         // inserted value is too high
437         parameters.putSingle("depth", "65536");
438         when(uriInfo.getQueryParameters()).thenReturn(parameters);
439
440         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
441             () -> ReadDataTransactionUtil.parseUriParameters(context, uriInfo));
442         // Bad request
443         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
444         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
445     }
446
447     /**
448      * Testing parsing of with-defaults parameter which value doesn't match report-all or report-all-tagged patterns
449      * - non-reporting setting.
450      */
451     @Test
452     public void parseUriParametersWithDefaultAndNonTaggedTest() {
453         // preparation of input data
454         final UriInfo uriInfo = mock(UriInfo.class);
455         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
456         parameters.putSingle("with-defaults", "explicit");
457         when(uriInfo.getQueryParameters()).thenReturn(parameters);
458
459         final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
460         assertSame(WithDefaultsParameter.EXPLICIT, writerParameters.getWithDefault());
461         assertFalse(writerParameters.isTagged());
462     }
463
464     /**
465      * Testing parsing of with-defaults parameter which value which is not supported.
466      */
467     @Test
468     public void parseUriParametersWithDefaultInvalidTest() {
469         // preparation of input data
470         final UriInfo uriInfo = mock(UriInfo.class);
471         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
472         parameters.putSingle("with-defaults", "invalid");
473         when(uriInfo.getQueryParameters()).thenReturn(parameters);
474
475         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
476             () -> ReadDataTransactionUtil.parseUriParameters(context, uriInfo));
477         final List<RestconfError> errors = ex.getErrors();
478         assertEquals(1, errors.size());
479         assertEquals(ErrorTag.INVALID_VALUE, errors.get(0).getErrorTag());
480     }
481
482     /**
483      * Testing parsing of with-defaults parameter which value matches 'report-all-tagged' setting - default value should
484      * be set to {@code null} and tagged flag should be set to {@code true}.
485      */
486     @Test
487     public void parseUriParametersWithDefaultAndTaggedTest() {
488         // preparation of input data
489         final UriInfo uriInfo = mock(UriInfo.class);
490         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
491         parameters.putSingle("with-defaults", "report-all-tagged");
492         when(uriInfo.getQueryParameters()).thenReturn(parameters);
493
494         final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
495         assertNull(writerParameters.getWithDefault());
496         assertTrue(writerParameters.isTagged());
497     }
498
499     /**
500      * Testing parsing of with-defaults parameter which value matches 'report-all' setting - default value should
501      * be set to {@code null} and tagged flag should be set to {@code false}.
502      */
503     @Test
504     public void parseUriParametersWithDefaultAndReportAllTest() {
505         // preparation of input data
506         final UriInfo uriInfo = mock(UriInfo.class);
507         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
508         parameters.putSingle("with-defaults", "report-all");
509         when(uriInfo.getQueryParameters()).thenReturn(parameters);
510
511         final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
512         assertNull(writerParameters.getWithDefault());
513         assertFalse(writerParameters.isTagged());
514     }
515
516     /**
517      * Test when parameter is present at most once.
518      */
519     @Test
520     public void getSingleParameterTest() {
521         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
522         parameters.putSingle(ContentParameter.uriName(), "all");
523         assertEquals("all", ReadDataTransactionUtil.getSingleParameter(parameters, ContentParameter.uriName()));
524     }
525
526     /**
527      * Test when parameter is present more than once.
528      */
529     @Test
530     public void getSingleParameterNegativeTest() {
531         final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
532         parameters.put(ContentParameter.uriName(), List.of("config", "nonconfig", "all"));
533
534         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
535             () -> ReadDataTransactionUtil.getSingleParameter(parameters, ContentParameter.uriName()));
536         final List<RestconfError> errors = ex.getErrors();
537         assertEquals(1, errors.size());
538
539         final RestconfError error = errors.get(0);
540         assertEquals("Error type is not correct", ErrorType.PROTOCOL, error.getErrorType());
541         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, error.getErrorTag());
542     }
543
544     /**
545      * Test when all parameters are allowed.
546      */
547     @Test
548     public void checkParametersTypesTest() {
549         ReadDataTransactionUtil.checkParametersTypes(Set.of("content"),
550             Set.of(ContentParameter.uriName(), DepthParameter.uriName()));
551     }
552
553     /**
554      * Test when not allowed parameter type is used.
555      */
556     @Test
557     public void checkParametersTypesNegativeTest() {
558         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
559             () -> ReadDataTransactionUtil.checkParametersTypes(Set.of("not-allowed-parameter"),
560                 Set.of(ContentParameter.uriName(), DepthParameter.uriName())));
561         final List<RestconfError> errors = ex.getErrors();
562         assertEquals(1, errors.size());
563
564         final RestconfError error = errors.get(0);
565         assertEquals("Error type is not correct", ErrorType.PROTOCOL, error.getErrorType());
566         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, error.getErrorTag());
567     }
568
569     /**
570      * Read specific type of data from data store via transaction.
571      *
572      * @param content        type of data to read (config, state, all)
573      * @param strategy       {@link RestconfStrategy} - wrapper for variables
574      * @return {@link NormalizedNode}
575      */
576     private @Nullable NormalizedNode readData(final @NonNull ContentParameter content,
577             final YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy) {
578         return ReadDataTransactionUtil.readData(content, path, strategy, null, schemaContext);
579     }
580 }