2 * Copyright (c) 2021 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.nb.rfc8040;
10 import static org.hamcrest.CoreMatchers.instanceOf;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertThrows;
15 import java.text.ParseException;
16 import java.util.Arrays;
17 import java.util.List;
18 import org.junit.Test;
19 import org.opendaylight.restconf.nb.rfc8040.ApiPath.ApiIdentifier;
20 import org.opendaylight.restconf.nb.rfc8040.ApiPath.ListInstance;
21 import org.opendaylight.restconf.nb.rfc8040.ApiPath.Step;
22 import org.opendaylight.yangtools.yang.common.UnresolvedQName;
24 public class ApiPathTest {
26 public void testNull() {
27 assertThrows(NullPointerException.class, () -> ApiPath.parse(null));
31 public void testEmpty() {
32 assertEquals(List.of(), parse("/"));
36 public void testSingleSlash() throws ParseException {
37 final var ex = assertThrows(ParseException.class, () -> ApiPath.parseUrl("/"));
38 assertEquals("Identifier may not be empty", ex.getMessage());
39 assertEquals(0, ex.getErrorOffset());
43 public void testTrailingSlash() throws ParseException {
44 final var ex = assertThrows(ParseException.class, () -> ApiPath.parseUrl("foo/"));
45 assertEquals("Identifier may not be empty", ex.getMessage());
46 assertEquals(4, ex.getErrorOffset());
50 public void testExample1() {
51 final var path = parse("/example-top:top/list1=key1,key2,key3/list2=key4,key5/X");
52 assertEquals(4, path.size());
53 assertApiIdentifier(path.get(0), "example-top", "top");
54 assertListInstance(path.get(1), null, "list1", "key1", "key2", "key3");
55 assertListInstance(path.get(2), null, "list2", "key4", "key5");
56 assertApiIdentifier(path.get(3), null, "X");
60 public void testExample2() {
61 final var path = parse("/example-top:top/Y=instance-value");
62 assertEquals(2, path.size());
63 assertApiIdentifier(path.get(0), "example-top", "top");
64 assertListInstance(path.get(1), null, "Y", "instance-value");
68 public void testExample3() {
69 final var path = parse("/example-top:top/list1=%2C%27\"%3A\"%20%2F,,foo");
70 assertEquals(2, path.size());
71 assertApiIdentifier(path.get(0), "example-top", "top");
72 assertListInstance(path.get(1), null, "list1", ",'\":\" /", "", "foo");
76 public void testEscapedColon() {
77 final var path = parse("/foo%3Afoo");
78 assertEquals(1, path.size());
79 assertApiIdentifier(path.get(0), "foo", "foo");
83 public void nonAsciiFirstIdentifier() {
84 final var ex = assertThrows(ParseException.class, () -> ApiPath.parse("a%80"));
85 assertEquals("Expecting %00-%7F, not %80", ex.getMessage());
86 assertEquals(1, ex.getErrorOffset());
90 public void nonAsciiSecondIdentifier() {
91 final var ex = assertThrows(ParseException.class, () -> ApiPath.parse("foo:a%80"));
92 assertEquals("Expecting %00-%7F, not %80", ex.getMessage());
93 assertEquals(5, ex.getErrorOffset());
97 public void testIllegalEscape() {
98 final var ex = assertThrows(ParseException.class, () -> ApiPath.parse("foo:foo=%41%FF%42%FF%43"));
99 assertEquals("Invalid UTF-8 sequence 'A�B�C': Input length = 1", ex.getMessage());
100 assertEquals(8, ex.getErrorOffset());
103 private static void assertApiIdentifier(final Step step, final String module, final String identifier) {
104 assertThat(step, instanceOf(ApiIdentifier.class));
105 assertEquals(module, step.module());
106 assertEquals(UnresolvedQName.unqualified(identifier), step.identifier());
109 private static void assertListInstance(final Step step, final String module, final String identifier,
110 final String... keyValues) {
111 assertThat(step, instanceOf(ListInstance.class));
112 assertEquals(module, step.module());
113 assertEquals(UnresolvedQName.unqualified(identifier), step.identifier());
114 assertEquals(Arrays.asList(keyValues), ((ListInstance) step).keyValues());
117 private static List<Step> parse(final String str) {
118 final String toParse = str.substring(1);
120 return ApiPath.parse(toParse).steps();
121 } catch (ParseException e) {
122 throw new AssertionError("Failed to parse \"" + toParse + "\"", e);