27ac70e6f6fcb5ee6fbc2abeab4b6ec53880189b
[yangtools.git] / parser / yang-parser-rfc7950 / src / test / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / path / PathExpressionParserTest.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o.  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.yangtools.yang.parser.rfc7950.stmt.path;
9
10 import static org.hamcrest.CoreMatchers.allOf;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.hamcrest.Matchers.containsString;
13 import static org.hamcrest.Matchers.startsWith;
14 import static org.junit.jupiter.api.Assertions.assertEquals;
15 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
16 import static org.junit.jupiter.api.Assertions.assertSame;
17 import static org.junit.jupiter.api.Assertions.assertThrows;
18 import static org.junit.jupiter.api.Assertions.assertTrue;
19 import static org.mockito.Mockito.doReturn;
20
21 import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.ImmutableSet;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.mockito.Mock;
27 import org.mockito.junit.jupiter.MockitoExtension;
28 import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
29 import org.opendaylight.yangtools.yang.model.api.PathExpression;
30 import org.opendaylight.yangtools.yang.model.api.PathExpression.DerefSteps;
31 import org.opendaylight.yangtools.yang.model.api.PathExpression.LocationPathSteps;
32 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
34 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
35 import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator;
36 import org.opendaylight.yangtools.yang.xpath.api.YangFunction;
37 import org.opendaylight.yangtools.yang.xpath.api.YangFunctionCallExpr;
38 import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath;
39 import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.Relative;
40 import org.opendaylight.yangtools.yang.xpath.api.YangPathExpr;
41 import org.opendaylight.yangtools.yang.xpath.api.YangQNameExpr;
42 import org.opendaylight.yangtools.yang.xpath.api.YangXPathAxis;
43
44 @ExtendWith(MockitoExtension.class)
45 public class PathExpressionParserTest {
46     @Mock
47     public StmtContext<?, ?, ?> ctx;
48     @Mock
49     public StatementSourceReference ref;
50
51     @SuppressWarnings("exports")
52     public final PathExpressionParser parser = new PathExpressionParser();
53
54     @BeforeEach
55     void before() {
56         doReturn(ref).when(ctx).sourceReference();
57     }
58
59     @Test
60     void testDerefPath() {
61         // deref() is not valid as per RFC7950, but we tolarate it.
62         final PathExpression deref = parser.parseExpression(ctx, "deref(../id)/../type");
63
64         final DerefSteps derefSteps = assertInstanceOf(DerefSteps.class, deref.getSteps());
65         assertEquals(YangLocationPath.relative(YangXPathAxis.PARENT.asStep(),
66             YangXPathAxis.CHILD.asStep(Unqualified.of("type"))), derefSteps.getRelativePath());
67         assertEquals(YangLocationPath.relative(YangXPathAxis.PARENT.asStep(),
68             YangXPathAxis.CHILD.asStep(Unqualified.of("id"))), derefSteps.getDerefArgument());
69     }
70
71     @Test
72     void testInvalidLeftParent() {
73         final var ex = assertThrows(SourceException.class, () -> parser.parseExpression(ctx, "foo("));
74         assertSame(ref, ex.getSourceReference());
75         assertThat(ex.getMessage(), allOf(
76             startsWith("extraneous input '(' expecting "),
77             containsString(" at 1:3 [at ")));
78     }
79
80     @Test
81     void testInvalidRightParent() {
82         final var ex = assertThrows(SourceException.class, () -> parser.parseExpression(ctx, "foo)"));
83         assertSame(ref, ex.getSourceReference());
84         assertThat(ex.getMessage(), allOf(
85             startsWith("extraneous input ')' expecting "),
86             containsString(" at 1:3 [at ")));
87     }
88
89     @Test
90     void testInvalidIdentifier() {
91         final var ex = assertThrows(SourceException.class, () -> parser.parseExpression(ctx, "foo%"));
92         assertSame(ref, ex.getSourceReference());
93         assertThat(ex.getMessage(), startsWith("token recognition error at: '%' at 1:3 [at "));
94     }
95
96     @Test
97     void testCurrentPredicateParsing() {
98         final YangLocationPath path = ((LocationPathSteps) parser.parseExpression(ctx,
99             "/device_types/device_type[type = current()/../type_text]/desc").getSteps()).getLocationPath();
100         assertTrue(path.isAbsolute());
101
102         path.getSteps();
103         assertEquals(ImmutableList.of(
104             YangXPathAxis.CHILD.asStep(Unqualified.of("device_types")),
105             YangXPathAxis.CHILD.asStep(Unqualified.of("device_type"),
106                 ImmutableSet.of(YangBinaryOperator.EQUALS.exprWith(
107                     YangQNameExpr.of(Unqualified.of("type")),
108                     YangPathExpr.of(YangFunctionCallExpr.of(YangFunction.CURRENT.getIdentifier()), Relative.relative(
109                         YangXPathAxis.PARENT.asStep(),
110                         YangXPathAxis.CHILD.asStep(Unqualified.of("type_text"))))))),
111             YangXPathAxis.CHILD.asStep(Unqualified.of("desc"))), path.getSteps());
112     }
113 }