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
8 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertThrows;
14 import java.text.ParseException;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
20 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
21 import org.opendaylight.restconf.nb.rfc8040.FieldsParam;
22 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
23 import org.opendaylight.yangtools.yang.common.ErrorTag;
24 import org.opendaylight.yangtools.yang.common.ErrorType;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.common.QNameModule;
27 import org.opendaylight.yangtools.yang.common.Revision;
28 import org.opendaylight.yangtools.yang.common.XMLNamespace;
29 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
30 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
31 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
33 public abstract class AbstractFieldsTranslatorTest<T> {
34 private static final QNameModule Q_NAME_MODULE_JUKEBOX = QNameModule.create(
35 XMLNamespace.of("http://example.com/ns/example-jukebox"), Revision.of("2015-04-04"));
36 private static final QNameModule Q_NAME_MODULE_TEST_SERVICES = QNameModule.create(
37 XMLNamespace.of("tests:test-services"), Revision.of("2019-03-25"));
38 private static final QNameModule Q_NAME_MODULE_AUGMENTED_JUKEBOX = QNameModule.create(
39 XMLNamespace.of("http://example.com/ns/augmented-jukebox"), Revision.of("2016-05-05"));
41 private InstanceIdentifierContext identifierJukebox;
42 private InstanceIdentifierContext identifierTestServices;
44 // FIXME: remove all this mocking -- just parse the underlying model and be done with it
47 private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
50 protected static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
53 protected static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
56 protected static final QName ARTIST_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "artist");
58 // container augmented library
59 protected static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX,
63 protected static final QName SPEED_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX, "speed");
66 public static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
69 protected static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
71 // container test data
72 private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
75 protected static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
77 // leaf type-of-service
78 protected static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
81 protected static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
84 protected static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
87 protected static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
89 // container next-data
90 protected static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
93 protected static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
95 // leaf-list protocols
96 protected static final QName PROTOCOLS_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "protocols");
99 public void setUp() throws Exception {
100 final EffectiveModelContext schemaContextJukebox =
101 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
102 identifierJukebox = InstanceIdentifierContext.ofStack(
103 SchemaInferenceStack.ofDataTreePath(schemaContextJukebox, JUKEBOX_Q_NAME));
105 final EffectiveModelContext schemaContextTestServices =
106 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
107 identifierTestServices = InstanceIdentifierContext.ofStack(
108 SchemaInferenceStack.ofDataTreePath(schemaContextTestServices, TEST_DATA_Q_NAME));
111 protected abstract List<T> translateFields(InstanceIdentifierContext context, FieldsParam fields);
114 * Test parse fields parameter containing only one child selected.
117 public void testSimplePath() {
118 final var result = translateFields(identifierJukebox, assertFields("library"));
119 assertNotNull(result);
120 assertSimplePath(result);
123 protected abstract void assertSimplePath(@NonNull List<T> result);
126 * Test parse fields parameter containing two child nodes selected.
129 public void testDoublePath() {
130 final var result = translateFields(identifierJukebox, assertFields("library;player"));
131 assertNotNull(result);
132 assertDoublePath(result);
135 protected abstract void assertDoublePath(@NonNull List<T> result);
138 * Test parse fields parameter containing sub-children selected delimited by slash.
141 public void testSubPath() {
142 final var result = translateFields(identifierJukebox, assertFields("library/artist/album/name"));
143 assertNotNull(result);
144 assertSubPath(result);
147 protected abstract void assertSubPath(@NonNull List<T> result);
150 * Test parse fields parameter containing sub-children selected delimited by parenthesis.
153 public void testChildrenPath() {
154 final var result = translateFields(identifierJukebox, assertFields("library(artist(album(name)))"));
155 assertNotNull(result);
156 assertChildrenPath(result);
159 protected abstract void assertChildrenPath(@NonNull List<T> result);
162 * Test parse fields parameter when augmentation with different namespace is used.
165 public void testNamespace() {
166 final var result = translateFields(identifierJukebox, assertFields("augmented-jukebox:augmented-library"));
167 assertNotNull(result);
168 assertNamespace(result);
171 protected abstract void assertNamespace(@NonNull List<T> result);
174 * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
175 * direct children of parent node - multiple children which are constructed using '/'.
178 public void testMultipleChildren1() {
179 final var result = translateFields(identifierTestServices,
180 assertFields("services(type-of-service;instance/instance-name;instance/provider)"));
181 assertNotNull(result);
182 assertMultipleChildren1(result);
185 protected abstract void assertMultipleChildren1(@NonNull List<T> result);
188 * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
189 * direct children of parent node - one of children nodes is typed using brackets, other is constructed using '/'.
192 public void testMultipleChildren2() {
193 final var result = translateFields(identifierTestServices,
194 assertFields("services(type-of-service;instance(instance-name;provider))"));
195 assertNotNull(result);
196 assertMultipleChildren2(result);
199 protected abstract void assertMultipleChildren2(@NonNull List<T> result);
202 * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
203 * direct children of parent node - multiple children with different parent nodes.
206 public void testMultipleChildren3() {
207 final var result = translateFields(identifierTestServices,
208 assertFields("services(instance/instance-name;type-of-service;next-data/next-service)"));
209 assertNotNull(result);
210 assertMultipleChildren3(result);
213 protected abstract void assertMultipleChildren3(@NonNull List<T> result);
216 public void testMultipleChildren4() {
217 final var result = translateFields(identifierTestServices,
218 assertFields("services(type-of-service;instance(instance-name;provider);next-data(next-service))"));
219 assertNotNull(result);
220 assertMultipleChildren4(result);
223 protected abstract void assertMultipleChildren4(@NonNull List<T> result);
226 public void testMultipleChildren5() {
227 final var result = translateFields(identifierTestServices,
228 assertFields("services(type-of-service;instance(instance-name;provider);next-data/next-service)"));
229 assertNotNull(result);
230 assertMultipleChildren5(result);
233 protected abstract void assertMultipleChildren5(@NonNull List<T> result);
236 public void testAugmentedChild() {
237 final var result = translateFields(identifierJukebox, assertFields("player/augmented-jukebox:speed"));
238 assertNotNull(result);
239 assertAugmentedChild(result);
242 protected abstract void assertAugmentedChild(@NonNull List<T> result);
245 public void testListFieldUnderList() {
246 final var result = translateFields(identifierTestServices, assertFields("services/instance"));
247 assertNotNull(result);
248 assertListFieldUnderList(result);
251 protected abstract void assertListFieldUnderList(@NonNull List<T> result);
254 public void testLeafList() {
255 final var result = translateFields(identifierTestServices, assertFields("protocols"));
256 assertNotNull(result);
257 assertLeafList(result);
260 protected abstract void assertLeafList(@NonNull List<T> result);
263 * Test parse fields parameter when not existing child node selected.
266 public void testMissingChildSchema() throws ParseException {
267 final FieldsParam input = FieldsParam.parse("library(not-existing)");
269 final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
270 () -> translateFields(identifierJukebox, input));
272 assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
273 assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
276 private static FieldsParam assertFields(final String input) {
278 return FieldsParam.parse(input);
279 } catch (ParseException e) {
280 throw new AssertionError(e);