2 * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
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;
16 import com.google.common.collect.Sets;
18 import java.util.List;
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;
41 * Unit test for {@link ParserFieldsParameter}.
43 @RunWith(MockitoJUnitRunner.class)
44 public class ParserFieldsParameterTest {
47 private InstanceIdentifierContext<ContainerSchemaNode> identifierJukebox;
50 private InstanceIdentifierContext<ContainerSchemaNode> identifierTestServices;
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"));
61 private ContainerSchemaNode containerJukebox;
62 private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
66 private ContainerSchemaNode containerPlayer;
67 private static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
71 private ContainerSchemaNode containerLibrary;
72 private static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
74 // container augmented library
76 private ContainerSchemaNode augmentedContainerLibrary;
77 private static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(
79 URI.create("http://example.com/ns/augmented-jukebox"),
80 Revision.of("2016-05-05")),
85 private ListSchemaNode listAlbum;
86 private static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
90 private LeafSchemaNode leafName;
91 private static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
93 // container test data
95 private ContainerSchemaNode containerTestData;
96 private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
100 private ListSchemaNode listServices;
101 private static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
103 // leaf type-of-service
105 private LeafSchemaNode leafTypeOfService;
106 private static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
110 private ListSchemaNode listInstance;
111 private static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
113 // leaf instance-name
115 private LeafSchemaNode leafInstanceName;
116 private static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
120 private LeafSchemaNode leafProvider;
121 private static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
123 // container next-data
125 private ContainerSchemaNode containerNextData;
126 private static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
130 private LeafSchemaNode leafNextService;
131 private static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
134 public void setUp() throws Exception {
135 final SchemaContext schemaContextJukebox =
136 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
137 initJukeboxSchemaNodes(schemaContextJukebox);
139 final SchemaContext schemaContextTestServices =
140 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
141 initTestServicesSchemaNodes(schemaContextTestServices);
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);
149 Mockito.when(containerLibrary.getQName()).thenReturn(LIBRARY_Q_NAME);
150 Mockito.when(containerJukebox.getDataChildByName(LIBRARY_Q_NAME)).thenReturn(containerLibrary);
152 Mockito.when(augmentedContainerLibrary.getQName()).thenReturn(AUGMENTED_LIBRARY_Q_NAME);
153 Mockito.when(containerJukebox.getDataChildByName(AUGMENTED_LIBRARY_Q_NAME))
154 .thenReturn(augmentedContainerLibrary);
156 Mockito.when(containerPlayer.getQName()).thenReturn(PLAYER_Q_NAME);
157 Mockito.when(containerJukebox.getDataChildByName(PLAYER_Q_NAME)).thenReturn(containerPlayer);
159 Mockito.when(listAlbum.getQName()).thenReturn(ALBUM_Q_NAME);
160 Mockito.when(containerLibrary.getDataChildByName(ALBUM_Q_NAME)).thenReturn(listAlbum);
162 Mockito.when(leafName.getQName()).thenReturn(NAME_Q_NAME);
163 Mockito.when(listAlbum.getDataChildByName(NAME_Q_NAME)).thenReturn(leafName);
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);
171 Mockito.when(listServices.getQName()).thenReturn(SERVICES_Q_NAME);
172 Mockito.when(containerTestData.getDataChildByName(SERVICES_Q_NAME)).thenReturn(listServices);
174 Mockito.when(leafTypeOfService.getQName()).thenReturn(TYPE_OF_SERVICE_Q_NAME);
175 Mockito.when(listServices.getDataChildByName(TYPE_OF_SERVICE_Q_NAME)).thenReturn(leafTypeOfService);
177 Mockito.when(listInstance.getQName()).thenReturn(INSTANCE_Q_NAME);
178 Mockito.when(listServices.getDataChildByName(INSTANCE_Q_NAME)).thenReturn(listInstance);
180 Mockito.when(leafInstanceName.getQName()).thenReturn(INSTANCE_NAME_Q_NAME);
181 Mockito.when(listInstance.getDataChildByName(INSTANCE_NAME_Q_NAME)).thenReturn(leafInstanceName);
183 Mockito.when(leafProvider.getQName()).thenReturn(PROVIDER_Q_NAME);
184 Mockito.when(listInstance.getDataChildByName(PROVIDER_Q_NAME)).thenReturn(leafProvider);
186 Mockito.when(containerNextData.getQName()).thenReturn(NEXT_DATA_Q_NAME);
187 Mockito.when(listServices.getDataChildByName(NEXT_DATA_Q_NAME)).thenReturn(containerNextData);
189 Mockito.when(leafNextService.getQName()).thenReturn(NEXT_SERVICE_Q_NAME);
190 Mockito.when(containerNextData.getDataChildByName(NEXT_SERVICE_Q_NAME)).thenReturn(leafNextService);
194 * Test parse fields parameter containing only one child selected.
197 public void parseFieldsParameterSimplePathTest() {
198 final String input = "library";
199 final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
201 assertNotNull(parsedFields);
202 assertEquals(1, parsedFields.size());
203 assertEquals(1, parsedFields.get(0).size());
204 assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
208 * Test parse fields parameter containing two child nodes selected.
211 public void parseFieldsParameterDoublePathTest() {
212 final String input = "library;player";
213 final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
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));
223 * Test parse fields parameter containing sub-children selected delimited by slash.
226 public void parseFieldsParameterSubPathTest() {
227 final String input = "library/album/name";
228 final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
230 assertNotNull(parsedFields);
231 assertEquals(3, parsedFields.size());
233 assertEquals(1, parsedFields.get(0).size());
234 assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
236 assertEquals(1, parsedFields.get(1).size());
237 assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
239 assertEquals(1, parsedFields.get(2).size());
240 assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
244 * Test parse fields parameter containing sub-children selected delimited by parenthesis.
247 public void parseFieldsParameterChildrenPathTest() {
248 final String input = "library(album(name))";
249 final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
251 assertNotNull(parsedFields);
252 assertEquals(3, parsedFields.size());
254 assertEquals(1, parsedFields.get(0).size());
255 assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
257 assertEquals(1, parsedFields.get(1).size());
258 assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
260 assertEquals(1, parsedFields.get(2).size());
261 assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
265 * Test parse fields parameter when augmentation with different namespace is used.
268 public void parseFieldsParameterNamespaceTest() {
269 final String input = "augmented-jukebox:augmented-library";
270 final List<Set<QName>> parsedFields = ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input);
272 assertNotNull(parsedFields);
273 assertEquals(1, parsedFields.size());
275 assertEquals(1, parsedFields.get(0).size());
276 assertTrue(parsedFields.get(0).contains(AUGMENTED_LIBRARY_Q_NAME));
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 '/'.
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);
288 assertNotNull(parsedFields);
289 assertEquals(parsedFields.size(), 3);
291 assertEquals(parsedFields.get(0).size(), 1);
292 assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
294 assertEquals(parsedFields.get(1).size(), 2);
295 assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
297 assertEquals(parsedFields.get(2).size(), 2);
298 assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
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 '/'.
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);
310 assertNotNull(parsedFields);
311 assertEquals(parsedFields.size(), 3);
313 assertEquals(parsedFields.get(0).size(), 1);
314 assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
316 assertEquals(parsedFields.get(1).size(), 2);
317 assertTrue(parsedFields.get(1).containsAll(Sets.newHashSet(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
319 assertEquals(parsedFields.get(2).size(), 2);
320 assertTrue(parsedFields.get(2).containsAll(Sets.newHashSet(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
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.
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);
332 assertNotNull(parsedFields);
333 assertEquals(parsedFields.size(), 3);
335 assertEquals(parsedFields.get(0).size(), 1);
336 assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
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)));
342 assertEquals(parsedFields.get(2).size(), 2);
343 assertTrue(parsedFields.get(2).containsAll(
344 Sets.newHashSet(INSTANCE_NAME_Q_NAME, NEXT_SERVICE_Q_NAME)));
348 * Test parse fields parameter containing not expected character.
351 public void parseFieldsParameterNotExpectedCharacterNegativeTest() {
352 final String input = "*";
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) {
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());
366 * Test parse fields parameter with missing closing parenthesis.
369 public void parseFieldsParameterMissingParenthesisNegativeTest() {
370 final String input = "library(";
373 ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
374 fail("Test should fail due to missing closing parenthesis");
375 } catch (final RestconfDocumentedException e) {
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());
384 * Test parse fields parameter when not existing child node selected.
387 public void parseFieldsParameterMissingChildNodeNegativeTest() {
388 final String input = "library(not-existing)";
391 ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
392 fail("Test should fail due to missing child node in parent node");
393 } catch (final RestconfDocumentedException e) {
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());
402 * Test parse fields parameter with unexpected character after parenthesis.
405 public void parseFieldsParameterAfterParenthesisNegativeTest() {
406 final String input = "library(album);";
409 ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
410 fail("Test should fail due to unexpected character after parenthesis");
411 } catch (final RestconfDocumentedException e) {
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());
420 * Test parse fields parameter with missing semicolon after parenthesis.
423 public void parseFieldsParameterMissingSemicolonNegativeTest() {
424 final String input = "library(album)player";
427 ParserFieldsParameter.parseFieldsParameter(this.identifierJukebox, input);
428 fail("Test should fail due to missing semicolon after parenthesis");
429 } catch (final RestconfDocumentedException e) {
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());