Remove deprecated Yin/YangStatementSourceImpl
[yangtools.git] / yang / yang-data-jaxen / src / test / java / org / opendaylight / yangtools / yang / data / jaxen / DerivedFromXPathFunctionTest.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  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
9 package org.opendaylight.yangtools.yang.data.jaxen;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.mockito.Mockito.mock;
17
18 import com.google.common.collect.BiMap;
19 import com.google.common.collect.HashBiMap;
20 import com.google.common.collect.ImmutableList;
21 import com.google.common.collect.ImmutableMap;
22 import com.google.common.collect.Maps;
23 import java.net.URI;
24 import java.text.ParseException;
25 import org.jaxen.Context;
26 import org.jaxen.Function;
27 import org.jaxen.FunctionCallException;
28 import org.junit.BeforeClass;
29 import org.junit.Test;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.common.QNameModule;
32 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
36 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
40 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathSchemaContext;
41 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
42 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
43 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
44
45 public class DerivedFromXPathFunctionTest {
46
47     private static JaxenSchemaContextFactory jaxenSchemaContextFactory;
48
49     private static QNameModule barModule;
50     private static QName myContainer;
51     private static QName myList;
52     private static QName keyLeaf;
53     private static QName idrefLeaf;
54     private static QName idC2Identity;
55
56     @BeforeClass
57     public static void setup() throws ParseException {
58         jaxenSchemaContextFactory = new JaxenSchemaContextFactory();
59
60         barModule = QNameModule.create(URI.create("bar-ns"),
61                 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
62         myContainer = QName.create(barModule, "my-container");
63         myList = QName.create(barModule, "my-list");
64         keyLeaf = QName.create(barModule, "key-leaf");
65         idrefLeaf = QName.create(barModule, "idref-leaf");
66         idC2Identity = QName.create(barModule, "id-c2");
67     }
68
69     @Test
70     public void testDerivedFromFunction() throws Exception {
71         // also includes test for derived-from-or-self function
72         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
73                 "/yang-xpath-functions-test/derived-from-function/foo.yang",
74                 "/yang-xpath-functions-test/derived-from-function/bar.yang");
75         assertNotNull(schemaContext);
76
77         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
78         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
79
80         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
81         converterBiMap.put("bar-prefix", barModule);
82
83         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
84                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
85
86         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
87                 buildPathToIdrefLeafNode());
88
89         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
90                 .getFunction(null, null, "derived-from");
91
92         assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
93         assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a4"));
94         assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b2"));
95         assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-b3"));
96         assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "id-b4"));
97
98         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a1"));
99         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a2"));
100         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b1"));
101         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-c1"));
102         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-c2"));
103
104         final Function derivedFromOrSelfFunction = normalizedNodeContextSupport.getFunctionContext()
105                 .getFunction(null, null, "derived-from-or-self");
106         assertTrue(getDerivedFromResult(derivedFromOrSelfFunction, normalizedNodeContext, "bar-prefix:id-c2"));
107     }
108
109     @Test
110     public void testInvalidTypeOfCorrespondingSchemaNode() throws Exception {
111         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
112                 "/yang-xpath-functions-test/derived-from-function/bar-invalid.yang");
113         assertNotNull(schemaContext);
114
115         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
116         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
117
118         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
119         converterBiMap.put("bar-prefix", barModule);
120
121         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
122                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
123
124         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
125                 buildPathToIdrefLeafNode());
126
127         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
128                 .getFunction(null, null, "derived-from");
129
130         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "some-identity"));
131     }
132
133     @Test
134     public void testInvalidNormalizedNodeValueType() throws Exception {
135         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
136                 "/yang-xpath-functions-test/derived-from-function/foo.yang",
137                 "/yang-xpath-functions-test/derived-from-function/bar.yang");
138         assertNotNull(schemaContext);
139
140         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
141         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode("should be QName"));
142
143         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
144         converterBiMap.put("bar-prefix", barModule);
145
146         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
147                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
148
149         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
150                 buildPathToIdrefLeafNode());
151
152         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
153                 .getFunction(null, null, "derived-from");
154
155         assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
156     }
157
158     @Test
159     public void shouldFailOnUnknownPrefixOfIdentity() throws Exception {
160         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
161                 "/yang-xpath-functions-test/derived-from-function/foo.yang",
162                 "/yang-xpath-functions-test/derived-from-function/bar.yang");
163         assertNotNull(schemaContext);
164
165         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
166         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
167
168         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
169         converterBiMap.put("bar-prefix", barModule);
170
171         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
172                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
173
174         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
175                 buildPathToIdrefLeafNode());
176
177         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
178                 .getFunction(null, null, "derived-from");
179
180         try {
181             getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "unknown-prefix:id-a3");
182             fail("Function call should have failed on unresolved prefix of the identity argument.");
183         } catch (IllegalArgumentException ex) {
184             assertEquals("Cannot resolve prefix 'unknown-prefix' from identity 'unknown-prefix:id-a3'.",
185                 ex.getMessage());
186         }
187     }
188
189     @Test
190     public void shouldFailOnMalformedIdentityArgument() throws Exception {
191         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
192                 "/yang-xpath-functions-test/derived-from-function/foo.yang",
193                 "/yang-xpath-functions-test/derived-from-function/bar.yang");
194         assertNotNull(schemaContext);
195
196         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
197         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
198
199         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
200         converterBiMap.put("bar-prefix", barModule);
201
202         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
203                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
204
205         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
206                 buildPathToIdrefLeafNode());
207
208         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
209                 .getFunction(null, null, "derived-from");
210
211         try {
212             getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo:bar:id-a3");
213             fail("Function call should have failed on malformed identity argument.");
214         } catch (IllegalArgumentException ex) {
215             assertEquals("Malformed identity argument: foo:bar:id-a3.", ex.getMessage());
216         }
217     }
218
219     @Test
220     public void shouldFailOnUnknownIdentityArgument() throws Exception {
221         final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
222                 "/yang-xpath-functions-test/derived-from-function/foo.yang",
223                 "/yang-xpath-functions-test/derived-from-function/bar.yang");
224         assertNotNull(schemaContext);
225
226         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
227         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
228
229         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
230         converterBiMap.put("bar-prefix", barModule);
231
232         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
233                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
234
235         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
236                 buildPathToIdrefLeafNode());
237
238         final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
239                 .getFunction(null, null, "derived-from");
240
241         try {
242             getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a333");
243             fail("Function call should have failed on unknown identity argument.");
244         } catch (IllegalArgumentException ex) {
245             assertTrue(ex.getMessage().startsWith(
246                     "Identity (foo-ns?revision=2017-04-03)id-a333 does not have a corresponding identity schema "
247                     + "node in the module"));
248         }
249     }
250
251     @Test
252     public void shouldFailOnInvalidNumberOfArguments() throws Exception {
253         final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
254         final Function derivedFromFunction = yangFunctionContext.getFunction(null, null, "derived-from");
255
256         final Context mockedContext = mock(Context.class);
257
258         try {
259             derivedFromFunction.call(mockedContext, ImmutableList.of("some-identity", "should not be here"));
260             fail("Function call should have failed on invalid number of arguments.");
261         } catch (final FunctionCallException ex) {
262             assertEquals("derived-from() takes two arguments: node-set nodes, string identity.", ex.getMessage());
263         }
264     }
265
266     @Test
267     public void shouldFailOnInvalidTypeOfArgument() throws Exception {
268         final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
269         final Function bitIsSetFunction = yangFunctionContext.getFunction(null, null, "derived-from");
270
271         final Context mockedContext = mock(Context.class);
272
273         try {
274             bitIsSetFunction.call(mockedContext, ImmutableList.of(100));
275             fail("Function call should have failed on invalid type of the identity argument.");
276         } catch (final FunctionCallException ex) {
277             assertEquals("Argument 'identity' of derived-from() function should be a String.", ex.getMessage());
278         }
279     }
280
281     private static boolean getDerivedFromResult(final Function derivedFromFunction, final NormalizedNodeContext nnCtx,
282             final String identityArg) throws Exception {
283         return (boolean) derivedFromFunction.call(nnCtx, ImmutableList.of(identityArg));
284     }
285
286     private static ContainerNode buildMyContainerNode(final Object idrefLeafValue) {
287         final LeafNode<?> idrefLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(idrefLeaf))
288                 .withValue(idrefLeafValue).build();
289
290         final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
291                 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
292                         new NodeIdentifierWithPredicates(myList, keyLeaf, "key-value"))
293                         .withChild(idrefLeafNode).build()).build();
294
295         final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
296                 new NodeIdentifier(myContainer)).withChild(myListNode).build();
297         return myContainerNode;
298     }
299
300     private static YangInstanceIdentifier buildPathToIdrefLeafNode() {
301         final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
302         final ImmutableMap<QName, Object> keys = builder.put(keyLeaf, "key-value").build();
303
304         final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
305                 .node(new NodeIdentifierWithPredicates(myList, keys)).node(idrefLeaf);
306         return path;
307     }
308 }