2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.server.spi;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
13 import java.text.ParseException;
14 import org.junit.jupiter.api.Test;
15 import org.opendaylight.restconf.api.ApiPath;
16 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
17 import org.opendaylight.restconf.common.errors.RestconfError;
18 import org.opendaylight.restconf.server.api.DatabindContext;
19 import org.opendaylight.yangtools.yang.common.ErrorTag;
20 import org.opendaylight.yangtools.yang.common.ErrorType;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.Uint8;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
27 private static final ApiPathNormalizer NORMALIZER = new ApiPathNormalizer(DatabindContext.ofModel(
28 YangParserTestUtils.parseYangResource("/nc1265.yang")));
29 private static final QName FOO = QName.create("nc1265", "foo");
30 private static final QName BAR = QName.create("nc1265", "bar");
31 private static final QName BAZ = QName.create("nc1265", "baz");
32 private static final QName KEY = QName.create("nc1265", "key");
33 private static final QName XYZZY = QName.create("nc1265", "xyzzy");
37 assertNormalized(YangInstanceIdentifier.builder()
39 .nodeWithKey(FOO, KEY, Uint8.valueOf(123))
40 .build(), "nc1265:foo=123");
45 assertNormalized(YangInstanceIdentifier.builder()
47 .nodeWithKey(BAZ, KEY, Uint8.valueOf(123))
48 .build(), "nc1265:baz=123");
52 void instanceIdentifierKey() {
53 assertNormalized(YangInstanceIdentifier.builder()
55 .nodeWithKey(BAR, KEY, YangInstanceIdentifier.builder()
57 .nodeWithKey(BAZ, KEY, Uint8.valueOf(123))
59 .build(), "nc1265:bar=%2Fnc1265:baz=123");
63 void unionKeyInstanceIdentifier() {
64 assertNormalized(YangInstanceIdentifier.builder()
66 .nodeWithKey(XYZZY, KEY, YangInstanceIdentifier.builder()
68 .nodeWithKey(BAZ, KEY, Uint8.valueOf(123))
70 .build(), "nc1265:xyzzy=%2Fnc1265:baz=123");
74 void unionKeyIdentityref() {
75 assertNormalized(YangInstanceIdentifier.builder()
77 .nodeWithKey(XYZZY, KEY, QName.create("nc1265", "base-id"))
78 .build(), "nc1265:xyzzy=nc1265:base-id");
82 void unionKeyLeafref() {
83 assertNormalized(YangInstanceIdentifier.builder()
85 .nodeWithKey(XYZZY, KEY, Uint8.valueOf(123))
86 .build(), "nc1265:xyzzy=123");
90 void unionKeyString() {
91 assertNormalized(YangInstanceIdentifier.builder()
93 .nodeWithKey(XYZZY, KEY, "abc")
94 .build(), "nc1265:xyzzy=abc");
98 void noslashInstanceIdentifierKey() {
99 final var error = assertRestconfError("nc1265:bar=nc1265:baz=123");
100 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
101 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
102 assertEquals("Invalid value 'nc1265:baz=123' for (nc1265)key", error.getErrorMessage());
103 assertEquals(null, error.getErrorInfo());
107 void malformedInstanceIdentifierKey() {
108 final var error = assertRestconfError("nc1265:bar=%2Fnc1265:baz=abc");
109 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
110 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
111 assertEquals("Invalid value '/nc1265:baz=abc' for (nc1265)key", error.getErrorMessage());
113 errors: [RestconfError [error-type: protocol, error-tag: invalid-value, error-message: Invalid value 'abc' \
114 for (nc1265)key, error-info: Incorrect lexical representation of integer value: abc.
115 An integer value can be defined as:
117 - a hexadecimal number (prefix 0x),%n - an octal number (prefix 0).
118 Signed values are allowed. Spaces between digits are NOT allowed.]]""", error.getErrorInfo());
121 private static void assertNormalized(final YangInstanceIdentifier expected, final String apiPath) {
122 assertEquals(expected, NORMALIZER.normalizeDataPath(assertApiPath(apiPath)).instance());
125 private static RestconfError assertRestconfError(final String apiPath) {
126 final var parsed = assertApiPath(apiPath);
128 final var ex = assertThrows(RestconfDocumentedException.class, () -> NORMALIZER.normalizeDataPath(parsed));
129 final var errors = ex.getErrors();
130 assertEquals(1, errors.size());
131 return errors.get(0);
134 private static ApiPath assertApiPath(final String apiPath) {
136 return ApiPath.parse(apiPath);
137 } catch (ParseException e) {
138 throw new AssertionError(e);