e5fd6b7acadb9e9cbdca34615ad98dd9be7eeb50
[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 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.when;
16
17 import com.google.common.collect.Sets;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Optional;
21 import java.util.Set;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.mockito.Mock;
26 import org.mockito.junit.MockitoJUnitRunner;
27 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
28 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
29 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
30 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
31 import org.opendaylight.yangtools.yang.common.ErrorType;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.common.QNameModule;
34 import org.opendaylight.yangtools.yang.common.Revision;
35 import org.opendaylight.yangtools.yang.common.XMLNamespace;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
40 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
43 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47
48 /**
49  * Unit test for {@link ParserFieldsParameter}.
50  */
51 @RunWith(MockitoJUnitRunner.class)
52 public class ParserFieldsParameterTest {
53
54     @Mock
55     private InstanceIdentifierContext<ContainerSchemaNode> identifierJukebox;
56
57     @Mock
58     private InstanceIdentifierContext<ContainerSchemaNode> identifierTestServices;
59
60     private static final QNameModule Q_NAME_MODULE_JUKEBOX = QNameModule.create(
61         XMLNamespace.of("http://example.com/ns/example-jukebox"), Revision.of("2015-04-04"));
62     private static final QNameModule Q_NAME_MODULE_TEST_SERVICES = QNameModule.create(
63         XMLNamespace.of("tests:test-services"), Revision.of("2019-03-25"));
64     private static final QNameModule Q_NAME_MODULE_AUGMENTED_JUKEBOX = QNameModule.create(
65         XMLNamespace.of("http://example.com/ns/augmented-jukebox"), Revision.of("2016-05-05"));
66
67     // container jukebox
68     @Mock
69     private ContainerSchemaNode containerJukebox;
70     private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
71
72     // container player
73     @Mock
74     private ContainerSchemaNode containerPlayer;
75     private static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
76
77     // container library
78     @Mock
79     private ContainerSchemaNode containerLibrary;
80     private static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
81
82     // container augmented library
83     @Mock
84     private ContainerSchemaNode augmentedContainerLibrary;
85     private static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX,
86             "augmented-library");
87
88     // augmentation that contains speed leaf
89     @Mock
90     private AugmentationSchemaNode speedAugmentation;
91
92     // leaf speed
93     @Mock
94     private LeafSchemaNode leafSpeed;
95     private static final QName SPEED_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX, "speed");
96
97     // list album
98     @Mock
99     private ListSchemaNode listAlbum;
100     private static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
101
102     // leaf name
103     @Mock
104     private LeafSchemaNode leafName;
105     private static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
106
107     // container test data
108     @Mock
109     private ContainerSchemaNode containerTestData;
110     private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
111
112     // list services
113     @Mock
114     private ListSchemaNode listServices;
115     private static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
116
117     // leaf type-of-service
118     @Mock
119     private LeafSchemaNode leafTypeOfService;
120     private static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
121
122     // list instance
123     @Mock
124     private ListSchemaNode listInstance;
125     private static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
126
127     // leaf instance-name
128     @Mock
129     private LeafSchemaNode leafInstanceName;
130     private static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
131
132     // leaf provider
133     @Mock
134     private LeafSchemaNode leafProvider;
135     private static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
136
137     // container next-data
138     @Mock
139     private ContainerSchemaNode containerNextData;
140     private static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
141
142     // leaf next-service
143     @Mock
144     private LeafSchemaNode leafNextService;
145     private static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
146
147     // leaf-list protocols
148     @Mock
149     private LeafListSchemaNode leafListProtocols;
150     private static final QName PROTOCOLS_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "protocols");
151
152     @Before
153     public void setUp() throws Exception {
154         final EffectiveModelContext schemaContextJukebox =
155                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
156         initJukeboxSchemaNodes(schemaContextJukebox);
157
158         final EffectiveModelContext schemaContextTestServices =
159                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
160         initTestServicesSchemaNodes(schemaContextTestServices);
161     }
162
163     private void initJukeboxSchemaNodes(final EffectiveModelContext schemaContext) {
164         when(identifierJukebox.getSchemaContext()).thenReturn(schemaContext);
165         when(containerJukebox.getQName()).thenReturn(JUKEBOX_Q_NAME);
166         when(identifierJukebox.getSchemaNode()).thenReturn(containerJukebox);
167
168         when(containerLibrary.getQName()).thenReturn(LIBRARY_Q_NAME);
169         when(containerJukebox.dataChildByName(LIBRARY_Q_NAME)).thenReturn(containerLibrary);
170
171         when(augmentedContainerLibrary.getQName()).thenReturn(AUGMENTED_LIBRARY_Q_NAME);
172         when(containerJukebox.dataChildByName(AUGMENTED_LIBRARY_Q_NAME))
173                 .thenReturn(augmentedContainerLibrary);
174
175         when(containerPlayer.getQName()).thenReturn(PLAYER_Q_NAME);
176         when(containerJukebox.dataChildByName(PLAYER_Q_NAME)).thenReturn(containerPlayer);
177
178         when(listAlbum.getQName()).thenReturn(ALBUM_Q_NAME);
179         when(containerLibrary.dataChildByName(ALBUM_Q_NAME)).thenReturn(listAlbum);
180
181         when(leafName.getQName()).thenReturn(NAME_Q_NAME);
182         when(listAlbum.dataChildByName(NAME_Q_NAME)).thenReturn(leafName);
183
184         when(leafSpeed.getQName()).thenReturn(SPEED_Q_NAME);
185         when(leafSpeed.isAugmenting()).thenReturn(true);
186         when(containerPlayer.dataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
187         when(containerPlayer.getDataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
188         doReturn(Collections.singletonList(leafSpeed)).when(speedAugmentation).getChildNodes();
189         doReturn(Collections.singleton(speedAugmentation)).when(containerPlayer).getAvailableAugmentations();
190         when(speedAugmentation.findDataChildByName(SPEED_Q_NAME)).thenReturn(Optional.of(leafSpeed));
191     }
192
193     private void initTestServicesSchemaNodes(final EffectiveModelContext schemaContext) {
194         when(identifierTestServices.getSchemaContext()).thenReturn(schemaContext);
195         when(containerTestData.getQName()).thenReturn(TEST_DATA_Q_NAME);
196         when(identifierTestServices.getSchemaNode()).thenReturn(containerTestData);
197
198         when(listServices.getQName()).thenReturn(SERVICES_Q_NAME);
199         when(containerTestData.dataChildByName(SERVICES_Q_NAME)).thenReturn(listServices);
200
201         when(leafListProtocols.getQName()).thenReturn(PROTOCOLS_Q_NAME);
202         when(containerTestData.dataChildByName(PROTOCOLS_Q_NAME)).thenReturn(leafListProtocols);
203
204         when(leafTypeOfService.getQName()).thenReturn(TYPE_OF_SERVICE_Q_NAME);
205         when(listServices.dataChildByName(TYPE_OF_SERVICE_Q_NAME)).thenReturn(leafTypeOfService);
206
207         when(listInstance.getQName()).thenReturn(INSTANCE_Q_NAME);
208         when(listServices.dataChildByName(INSTANCE_Q_NAME)).thenReturn(listInstance);
209
210         when(leafInstanceName.getQName()).thenReturn(INSTANCE_NAME_Q_NAME);
211         when(listInstance.dataChildByName(INSTANCE_NAME_Q_NAME)).thenReturn(leafInstanceName);
212
213         when(leafProvider.getQName()).thenReturn(PROVIDER_Q_NAME);
214         when(listInstance.dataChildByName(PROVIDER_Q_NAME)).thenReturn(leafProvider);
215
216         when(containerNextData.getQName()).thenReturn(NEXT_DATA_Q_NAME);
217         when(listServices.dataChildByName(NEXT_DATA_Q_NAME)).thenReturn(containerNextData);
218
219         when(leafNextService.getQName()).thenReturn(NEXT_SERVICE_Q_NAME);
220         when(containerNextData.dataChildByName(NEXT_SERVICE_Q_NAME)).thenReturn(leafNextService);
221     }
222
223     /**
224      * Test parse fields parameter containing only one child selected.
225      */
226     @Test
227     public void parseFieldsParameterSimplePathTest() {
228         final String input = "library";
229         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
230
231         assertNotNull(parsedFields);
232         assertEquals(1, parsedFields.size());
233         assertEquals(1, parsedFields.get(0).size());
234         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
235     }
236
237     /**
238      * Test parse fields parameter containing two child nodes selected.
239      */
240     @Test
241     public void parseFieldsParameterDoublePathTest() {
242         final String input = "library;player";
243         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
244
245         assertNotNull(parsedFields);
246         assertEquals(1, parsedFields.size());
247         assertEquals(2, parsedFields.get(0).size());
248         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
249         assertTrue(parsedFields.get(0).contains(PLAYER_Q_NAME));
250     }
251
252     /**
253      * Test parse fields parameter containing sub-children selected delimited by slash.
254      */
255     @Test
256     public void parseFieldsParameterSubPathTest() {
257         final String input = "library/album/name";
258         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
259
260         assertNotNull(parsedFields);
261         assertEquals(3, parsedFields.size());
262
263         assertEquals(1, parsedFields.get(0).size());
264         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
265
266         assertEquals(1, parsedFields.get(1).size());
267         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
268
269         assertEquals(1, parsedFields.get(2).size());
270         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
271     }
272
273     /**
274      * Test parse fields parameter containing sub-children selected delimited by parenthesis.
275      */
276     @Test
277     public void parseFieldsParameterChildrenPathTest() {
278         final String input = "library(album(name))";
279         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
280
281         assertNotNull(parsedFields);
282         assertEquals(3, parsedFields.size());
283
284         assertEquals(1, parsedFields.get(0).size());
285         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
286
287         assertEquals(1, parsedFields.get(1).size());
288         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
289
290         assertEquals(1, parsedFields.get(2).size());
291         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
292     }
293
294     /**
295      * Test parse fields parameter when augmentation with different namespace is used.
296      */
297     @Test
298     public void parseFieldsParameterNamespaceTest() {
299         final String input = "augmented-jukebox:augmented-library";
300         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
301
302         assertNotNull(parsedFields);
303         assertEquals(1, parsedFields.size());
304
305         assertEquals(1, parsedFields.get(0).size());
306         assertTrue(parsedFields.get(0).contains(AUGMENTED_LIBRARY_Q_NAME));
307     }
308
309     /**
310      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
311      * direct children of parent node - multiple children which are constructed using '/'.
312      */
313     @Test
314     public void parseFieldsParameterWithMultipleChildrenTest1() {
315         final String input = "services(type-of-service;instance/instance-name;instance/provider)";
316         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
317
318         assertNotNull(parsedFields);
319         assertEquals(parsedFields.size(), 3);
320
321         assertEquals(parsedFields.get(0).size(), 1);
322         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
323
324         assertEquals(parsedFields.get(1).size(), 2);
325         assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
326
327         assertEquals(parsedFields.get(2).size(), 2);
328         assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
329     }
330
331     /**
332      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
333      * direct children of parent node - one of children nodes is typed using brackets, other is constructed using '/'.
334      */
335     @Test
336     public void parseFieldsParameterWithMultipleChildrenTest2() {
337         final String input = "services(type-of-service;instance(instance-name;provider))";
338         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
339
340         assertNotNull(parsedFields);
341         assertEquals(parsedFields.size(), 3);
342
343         assertEquals(parsedFields.get(0).size(), 1);
344         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
345
346         assertEquals(parsedFields.get(1).size(), 2);
347         assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
348
349         assertEquals(parsedFields.get(2).size(), 2);
350         assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
351     }
352
353     /**
354      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
355      * direct children of parent node - multiple children with different parent nodes.
356      */
357     @Test
358     public void parseFieldsParameterWithMultipleChildrenTest3() {
359         final String input = "services(instance/instance-name;type-of-service;next-data/next-service)";
360         final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierTestServices, input);
361
362         assertNotNull(parsedFields);
363         assertEquals(parsedFields.size(), 3);
364
365         assertEquals(parsedFields.get(0).size(), 1);
366         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
367
368         assertEquals(parsedFields.get(1).size(), 3);
369         assertTrue(parsedFields.get(1).containsAll(
370                 Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME, NEXT_DATA_Q_NAME)));
371
372         assertEquals(parsedFields.get(2).size(), 2);
373         assertTrue(parsedFields.get(2).containsAll(
374                 Sets.newHashSet(INSTANCE_NAME_Q_NAME, NEXT_SERVICE_Q_NAME)));
375     }
376
377     /**
378      * Test parse fields parameter containing not expected character.
379      */
380     @Test
381     public void parseFieldsParameterNotExpectedCharacterNegativeTest() {
382         final String input = "*";
383
384         try {
385             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
386             fail("Test should fail due to not expected character used in parameter input value");
387         } catch (final RestconfDocumentedException e) {
388             // Bad request
389             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
390             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
391             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
392         }
393     }
394
395     /**
396      * Test parse fields parameter with missing closing parenthesis.
397      */
398     @Test
399     public void parseFieldsParameterMissingParenthesisNegativeTest() {
400         final String input = "library(";
401
402         try {
403             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
404             fail("Test should fail due to missing closing parenthesis");
405         } catch (final RestconfDocumentedException e) {
406             // Bad request
407             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
408             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
409             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
410         }
411     }
412
413     /**
414      * Test parse fields parameter when not existing child node selected.
415      */
416     @Test
417     public void parseFieldsParameterMissingChildNodeNegativeTest() {
418         final String input = "library(not-existing)";
419
420         try {
421             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
422             fail("Test should fail due to missing child node in parent node");
423         } catch (final RestconfDocumentedException e) {
424             // Bad request
425             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
426             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
427             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
428         }
429     }
430
431     /**
432      * Test parse fields parameter with unexpected character after parenthesis.
433      */
434     @Test
435     public void parseFieldsParameterAfterParenthesisNegativeTest() {
436         final String input = "library(album);";
437
438         try {
439             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
440             fail("Test should fail due to unexpected character after parenthesis");
441         } catch (final RestconfDocumentedException e) {
442             // Bad request
443             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
444             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
445             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
446         }
447     }
448
449     /**
450      * Test parse fields parameter with missing semicolon after parenthesis.
451      */
452     @Test
453     public void parseFieldsParameterMissingSemicolonNegativeTest() {
454         final String input = "library(album)player";
455
456         try {
457             ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
458             fail("Test should fail due to missing semicolon after parenthesis");
459         } catch (final RestconfDocumentedException e) {
460             // Bad request
461             assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
462             assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
463             assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
464         }
465     }
466
467     @Test
468     public void parseTopLevelContainerToPathTest() {
469         final String input = "library";
470         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
471                 identifierJukebox, input);
472
473         assertNotNull(parsedFields);
474         assertEquals(1, parsedFields.size());
475         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
476         assertEquals(1, pathArguments.size());
477         assertEquals(LIBRARY_Q_NAME, pathArguments.get(0).getNodeType());
478     }
479
480     @Test
481     public void parseTwoTopLevelContainersToPathsTest() {
482         final String input = "library;player";
483         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
484                 identifierJukebox, input);
485
486         assertNotNull(parsedFields);
487         assertEquals(2, parsedFields.size());
488
489         final Optional<YangInstanceIdentifier> libraryPath = findPath(parsedFields, LIBRARY_Q_NAME);
490         assertTrue(libraryPath.isPresent());
491         assertEquals(1, libraryPath.get().getPathArguments().size());
492
493         final Optional<YangInstanceIdentifier> playerPath = findPath(parsedFields, PLAYER_Q_NAME);
494         assertTrue(playerPath.isPresent());
495         assertEquals(1, libraryPath.get().getPathArguments().size());
496     }
497
498     @Test
499     public void parseNestedLeafToPathTest() {
500         final String input = "library/album/name";
501         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
502                 identifierJukebox, input);
503
504         assertEquals(1, parsedFields.size());
505         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
506         assertEquals(3, pathArguments.size());
507
508         assertEquals(LIBRARY_Q_NAME, pathArguments.get(0).getNodeType());
509         assertEquals(ALBUM_Q_NAME, pathArguments.get(1).getNodeType());
510         assertEquals(NAME_Q_NAME, pathArguments.get(2).getNodeType());
511     }
512
513     @Test
514     public void parseAugmentedLeafToPathTest() {
515         final String input = "player/augmented-jukebox:speed";
516         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
517                 identifierJukebox, input);
518
519         assertEquals(1, parsedFields.size());
520         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
521
522         assertEquals(3, pathArguments.size());
523         assertEquals(PLAYER_Q_NAME, pathArguments.get(0).getNodeType());
524         assertTrue(pathArguments.get(1) instanceof AugmentationIdentifier);
525         assertEquals(SPEED_Q_NAME, pathArguments.get(2).getNodeType());
526     }
527
528     @Test
529     public void parseMultipleFieldsOnDifferentLevelsToPathsTest() {
530         final String input = "services(type-of-service;instance/instance-name;instance/provider)";
531         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
532                 identifierTestServices, input);
533
534         assertEquals(3, parsedFields.size());
535
536         final Optional<YangInstanceIdentifier> tosPath = findPath(parsedFields, TYPE_OF_SERVICE_Q_NAME);
537         assertTrue(tosPath.isPresent());
538         assertEquals(2, tosPath.get().getPathArguments().size());
539
540         final Optional<YangInstanceIdentifier> instanceNamePath = findPath(parsedFields, INSTANCE_NAME_Q_NAME);
541         assertTrue(instanceNamePath.isPresent());
542         assertEquals(3, instanceNamePath.get().getPathArguments().size());
543
544         final Optional<YangInstanceIdentifier> providerPath = findPath(parsedFields, PROVIDER_Q_NAME);
545         assertTrue(providerPath.isPresent());
546         assertEquals(3, providerPath.get().getPathArguments().size());
547     }
548
549     @Test
550     public void parseListFieldUnderListToPathTest() {
551         final String input = "services/instance";
552         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
553                 identifierTestServices, input);
554
555         assertEquals(1, parsedFields.size());
556         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
557         assertEquals(2, pathArguments.size());
558
559         assertEquals(SERVICES_Q_NAME, pathArguments.get(0).getNodeType());
560         assertTrue(pathArguments.get(0) instanceof NodeIdentifier);
561         assertEquals(INSTANCE_Q_NAME, pathArguments.get(1).getNodeType());
562         assertTrue(pathArguments.get(1) instanceof NodeIdentifier);
563     }
564
565     @Test
566     public void parseLeafListFieldToPathTest() {
567         final String input = "protocols";
568         final List<YangInstanceIdentifier> parsedFields = ParserFieldsParameter.parseFieldsPaths(
569                 identifierTestServices, input);
570
571         assertEquals(1, parsedFields.size());
572         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
573         assertEquals(1, pathArguments.size());
574         assertTrue(pathArguments.get(0) instanceof NodeIdentifier);
575         assertEquals(PROTOCOLS_Q_NAME, pathArguments.get(0).getNodeType());
576     }
577
578     private static Optional<YangInstanceIdentifier> findPath(final List<YangInstanceIdentifier> paths,
579                                                              final QName lastPathArg) {
580         return paths.stream()
581                 .filter(path -> lastPathArg.equals(path.getLastPathArgument().getNodeType()))
582                 .findAny();
583     }
584 }