Merge "Hide credentials from logs"
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / utils / parser / ParserFieldsParameterTest.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.utils.parser;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15
16 import com.google.common.collect.Sets;
17 import java.net.URI;
18 import java.util.List;
19 import java.util.Set;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.Mock;
24 import org.mockito.Mockito;
25 import org.mockito.junit.MockitoJUnitRunner;
26 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
27 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
28 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
29 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
30 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.common.QNameModule;
33 import org.opendaylight.yangtools.yang.common.Revision;
34 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
39
40 /**
41  * Unit test for {@link ParserFieldsParameter}.
42  */
43 @RunWith(MockitoJUnitRunner.class)
44 public class ParserFieldsParameterTest {
45
46     @Mock
47     private InstanceIdentifierContext<ContainerSchemaNode> identifierJukebox;
48
49     @Mock
50     private InstanceIdentifierContext<ContainerSchemaNode> identifierTestServices;
51
52     private static final QNameModule Q_NAME_MODULE_JUKEBOX = QNameModule.create(
53             URI.create("http://example.com/ns/example-jukebox"),
54             Revision.of("2015-04-04"));
55     private static final QNameModule Q_NAME_MODULE_TEST_SERVICES = QNameModule.create(
56             URI.create("tests:test-services"),
57             Revision.of("2019-03-25"));
58
59     // container jukebox
60     @Mock
61     private ContainerSchemaNode containerJukebox;
62     private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
63
64     // container player
65     @Mock
66     private ContainerSchemaNode containerPlayer;
67     private static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
68
69     // container library
70     @Mock
71     private ContainerSchemaNode containerLibrary;
72     private static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
73
74     // container augmented library
75     @Mock
76     private ContainerSchemaNode augmentedContainerLibrary;
77     private static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(
78             QNameModule.create(
79                     URI.create("http://example.com/ns/augmented-jukebox"),
80                     Revision.of("2016-05-05")),
81             "augmented-library");
82
83     // list album
84     @Mock
85     private ListSchemaNode listAlbum;
86     private static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
87
88     // leaf name
89     @Mock
90     private LeafSchemaNode leafName;
91     private static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
92
93     // container test data
94     @Mock
95     private ContainerSchemaNode containerTestData;
96     private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
97
98     // list services
99     @Mock
100     private ListSchemaNode listServices;
101     private static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
102
103     // leaf type-of-service
104     @Mock
105     private LeafSchemaNode leafTypeOfService;
106     private static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
107
108     // list instance
109     @Mock
110     private ListSchemaNode listInstance;
111     private static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
112
113     // leaf instance-name
114     @Mock
115     private LeafSchemaNode leafInstanceName;
116     private static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
117
118     // leaf provider
119     @Mock
120     private LeafSchemaNode leafProvider;
121     private static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
122
123     // container next-data
124     @Mock
125     private ContainerSchemaNode containerNextData;
126     private static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
127
128     // leaf next-service
129     @Mock
130     private LeafSchemaNode leafNextService;
131     private static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
132
133     @Before
134     public void setUp() throws Exception {
135         final SchemaContext schemaContextJukebox =
136                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
137         initJukeboxSchemaNodes(schemaContextJukebox);
138
139         final SchemaContext schemaContextTestServices =
140                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
141         initTestServicesSchemaNodes(schemaContextTestServices);
142     }
143
144     private void initJukeboxSchemaNodes(final SchemaContext schemaContext) {
145         Mockito.when(identifierJukebox.getSchemaContext()).thenReturn(schemaContext);
146         Mockito.when(containerJukebox.getQName()).thenReturn(JUKEBOX_Q_NAME);
147         Mockito.when(identifierJukebox.getSchemaNode()).thenReturn(containerJukebox);
148
149         Mockito.when(containerLibrary.getQName()).thenReturn(LIBRARY_Q_NAME);
150         Mockito.when(containerJukebox.getDataChildByName(LIBRARY_Q_NAME)).thenReturn(containerLibrary);
151
152         Mockito.when(augmentedContainerLibrary.getQName()).thenReturn(AUGMENTED_LIBRARY_Q_NAME);
153         Mockito.when(containerJukebox.getDataChildByName(AUGMENTED_LIBRARY_Q_NAME))
154                 .thenReturn(augmentedContainerLibrary);
155
156         Mockito.when(containerPlayer.getQName()).thenReturn(PLAYER_Q_NAME);
157         Mockito.when(containerJukebox.getDataChildByName(PLAYER_Q_NAME)).thenReturn(containerPlayer);
158
159         Mockito.when(listAlbum.getQName()).thenReturn(ALBUM_Q_NAME);
160         Mockito.when(containerLibrary.getDataChildByName(ALBUM_Q_NAME)).thenReturn(listAlbum);
161
162         Mockito.when(leafName.getQName()).thenReturn(NAME_Q_NAME);
163         Mockito.when(listAlbum.getDataChildByName(NAME_Q_NAME)).thenReturn(leafName);
164     }
165
166     private void initTestServicesSchemaNodes(final SchemaContext schemaContext) {
167         Mockito.when(identifierTestServices.getSchemaContext()).thenReturn(schemaContext);
168         Mockito.when(containerTestData.getQName()).thenReturn(TEST_DATA_Q_NAME);
169         Mockito.when(identifierTestServices.getSchemaNode()).thenReturn(containerTestData);
170
171         Mockito.when(listServices.getQName()).thenReturn(SERVICES_Q_NAME);
172         Mockito.when(containerTestData.getDataChildByName(SERVICES_Q_NAME)).thenReturn(listServices);
173
174         Mockito.when(leafTypeOfService.getQName()).thenReturn(TYPE_OF_SERVICE_Q_NAME);
175         Mockito.when(listServices.getDataChildByName(TYPE_OF_SERVICE_Q_NAME)).thenReturn(leafTypeOfService);
176
177         Mockito.when(listInstance.getQName()).thenReturn(INSTANCE_Q_NAME);
178         Mockito.when(listServices.getDataChildByName(INSTANCE_Q_NAME)).thenReturn(listInstance);
179
180         Mockito.when(leafInstanceName.getQName()).thenReturn(INSTANCE_NAME_Q_NAME);
181         Mockito.when(listInstance.getDataChildByName(INSTANCE_NAME_Q_NAME)).thenReturn(leafInstanceName);
182
183         Mockito.when(leafProvider.getQName()).thenReturn(PROVIDER_Q_NAME);
184         Mockito.when(listInstance.getDataChildByName(PROVIDER_Q_NAME)).thenReturn(leafProvider);
185
186         Mockito.when(containerNextData.getQName()).thenReturn(NEXT_DATA_Q_NAME);
187         Mockito.when(listServices.getDataChildByName(NEXT_DATA_Q_NAME)).thenReturn(containerNextData);
188
189         Mockito.when(leafNextService.getQName()).thenReturn(NEXT_SERVICE_Q_NAME);
190         Mockito.when(containerNextData.getDataChildByName(NEXT_SERVICE_Q_NAME)).thenReturn(leafNextService);
191     }
192
193     /**
194      * Test parse fields parameter containing only one child selected.
195      */
196     @Test
197     public void parseFieldsParameterSimplePathTest() {
198         final String input = "library";
199         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
200
201         assertNotNull(parsedFields);
202         assertEquals(1, parsedFields.size());
203         assertEquals(1, parsedFields.get(0).size());
204         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
205     }
206
207     /**
208      * Test parse fields parameter containing two child nodes selected.
209      */
210     @Test
211     public void parseFieldsParameterDoublePathTest() {
212         final String input = "library;player";
213         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
214
215         assertNotNull(parsedFields);
216         assertEquals(1, parsedFields.size());
217         assertEquals(2, parsedFields.get(0).size());
218         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
219         assertTrue(parsedFields.get(0).contains(PLAYER_Q_NAME));
220     }
221
222     /**
223      * Test parse fields parameter containing sub-children selected delimited by slash.
224      */
225     @Test
226     public void parseFieldsParameterSubPathTest() {
227         final String input = "library/album/name";
228         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
229
230         assertNotNull(parsedFields);
231         assertEquals(3, parsedFields.size());
232
233         assertEquals(1, parsedFields.get(0).size());
234         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
235
236         assertEquals(1, parsedFields.get(1).size());
237         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
238
239         assertEquals(1, parsedFields.get(2).size());
240         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
241     }
242
243     /**
244      * Test parse fields parameter containing sub-children selected delimited by parenthesis.
245      */
246     @Test
247     public void parseFieldsParameterChildrenPathTest() {
248         final String input = "library(album(name))";
249         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
250
251         assertNotNull(parsedFields);
252         assertEquals(3, parsedFields.size());
253
254         assertEquals(1, parsedFields.get(0).size());
255         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
256
257         assertEquals(1, parsedFields.get(1).size());
258         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
259
260         assertEquals(1, parsedFields.get(2).size());
261         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
262     }
263
264     /**
265      * Test parse fields parameter when augmentation with different namespace is used.
266      */
267     @Test
268     public void parseFieldsParameterNamespaceTest() {
269         final String input = "augmented-jukebox:augmented-library";
270         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
271
272         assertNotNull(parsedFields);
273         assertEquals(1, parsedFields.size());
274
275         assertEquals(1, parsedFields.get(0).size());
276         assertTrue(parsedFields.get(0).contains(AUGMENTED_LIBRARY_Q_NAME));
277     }
278
279     /**
280      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
281      * direct children of parent node - multiple children which are constructed using '/'.
282      */
283     @Test
284     public void parseFieldsParameterWithMultipleChildrenTest1() {
285         final String input = "services(type-of-service;instance/instance-name;instance/provider)";
286         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
287
288         assertNotNull(parsedFields);
289         assertEquals(parsedFields.size(), 3);
290
291         assertEquals(parsedFields.get(0).size(), 1);
292         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
293
294         assertEquals(parsedFields.get(1).size(), 2);
295         assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
296
297         assertEquals(parsedFields.get(2).size(), 2);
298         assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
299     }
300
301     /**
302      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
303      * direct children of parent node - one of children nodes is typed using brackets, other is constructed using '/'.
304      */
305     @Test
306     public void parseFieldsParameterWithMultipleChildrenTest2() {
307         final String input = "services(type-of-service;instance(instance-name;provider))";
308         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
309
310         assertNotNull(parsedFields);
311         assertEquals(parsedFields.size(), 3);
312
313         assertEquals(parsedFields.get(0).size(), 1);
314         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
315
316         assertEquals(parsedFields.get(1).size(), 2);
317         assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
318
319         assertEquals(parsedFields.get(2).size(), 2);
320         assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
321     }
322
323     /**
324      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
325      * direct children of parent node - multiple children with different parent nodes.
326      */
327     @Test
328     public void parseFieldsParameterWithMultipleChildrenTest3() {
329         final String input = "services(instance/instance-name;type-of-service;next-data/next-service)";
330         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
331
332         assertNotNull(parsedFields);
333         assertEquals(parsedFields.size(), 3);
334
335         assertEquals(parsedFields.get(0).size(), 1);
336         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
337
338         assertEquals(parsedFields.get(1).size(), 3);
339         assertTrue(parsedFields.get(1).containsAll(
340                 Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME, NEXT_DATA_Q_NAME)));
341
342         assertEquals(parsedFields.get(2).size(), 2);
343         assertTrue(parsedFields.get(2).containsAll(
344                 Sets.newHashSet(INSTANCE_NAME_Q_NAME, NEXT_SERVICE_Q_NAME)));
345     }
346
347     /**
348      * Test parse fields parameter containing not expected character.
349      */
350     @Test
351     public void parseFieldsParameterNotExpectedCharacterNegativeTest() {
352         final String input = "*";
353
354         try {
355             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
356             fail("Test should fail due to not expected character used in parameter input value");
357         } catch (final RestconfDocumentedException e) {
358             // Bad request
359             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
360             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
361             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
362         }
363     }
364
365     /**
366      * Test parse fields parameter with missing closing parenthesis.
367      */
368     @Test
369     public void parseFieldsParameterMissingParenthesisNegativeTest() {
370         final String input = "library(";
371
372         try {
373             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
374             fail("Test should fail due to missing closing parenthesis");
375         } catch (final RestconfDocumentedException e) {
376             // Bad request
377             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
378             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
379             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
380         }
381     }
382
383     /**
384      * Test parse fields parameter when not existing child node selected.
385      */
386     @Test
387     public void parseFieldsParameterMissingChildNodeNegativeTest() {
388         final String input = "library(not-existing)";
389
390         try {
391             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
392             fail("Test should fail due to missing child node in parent node");
393         } catch (final RestconfDocumentedException e) {
394             // Bad request
395             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
396             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
397             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
398         }
399     }
400
401     /**
402      * Test parse fields parameter with unexpected character after parenthesis.
403      */
404     @Test
405     public void parseFieldsParameterAfterParenthesisNegativeTest() {
406         final String input = "library(album);";
407
408         try {
409             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
410             fail("Test should fail due to unexpected character after parenthesis");
411         } catch (final RestconfDocumentedException e) {
412             // Bad request
413             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
414             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
415             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
416         }
417     }
418
419     /**
420      * Test parse fields parameter with missing semicolon after parenthesis.
421      */
422     @Test
423     public void parseFieldsParameterMissingSemicolonNegativeTest() {
424         final String input = "library(album)player";
425
426         try {
427             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
428             fail("Test should fail due to missing semicolon after parenthesis");
429         } catch (final RestconfDocumentedException e) {
430             // Bad request
431             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
432             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
433             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
434         }
435     }
436
437
438 }