2 * Copyright (c) 2017 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
9 package org.opendaylight.yangtools.yang.data.jaxen;
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;
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;
24 import org.jaxen.Context;
25 import org.jaxen.Function;
26 import org.jaxen.FunctionCallException;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.QNameModule;
31 import org.opendaylight.yangtools.yang.common.Revision;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
35 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
39 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathSchemaContext;
40 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
44 public class DerivedFromXPathFunctionTest {
46 private static JaxenSchemaContextFactory jaxenSchemaContextFactory;
48 private static QNameModule barModule;
49 private static QName myContainer;
50 private static QName myList;
51 private static QName keyLeaf;
52 private static QName idrefLeaf;
53 private static QName idC2Identity;
56 public static void setup() {
57 jaxenSchemaContextFactory = new JaxenSchemaContextFactory();
59 barModule = QNameModule.create(URI.create("bar-ns"), Revision.valueOf("2017-04-03"));
60 myContainer = QName.create(barModule, "my-container");
61 myList = QName.create(barModule, "my-list");
62 keyLeaf = QName.create(barModule, "key-leaf");
63 idrefLeaf = QName.create(barModule, "idref-leaf");
64 idC2Identity = QName.create(barModule, "id-c2");
68 public void testDerivedFromFunction() throws Exception {
69 // also includes test for derived-from-or-self function
70 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
71 "/yang-xpath-functions-test/derived-from-function/foo.yang",
72 "/yang-xpath-functions-test/derived-from-function/bar.yang");
73 assertNotNull(schemaContext);
75 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
76 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
78 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
79 converterBiMap.put("bar-prefix", barModule);
81 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
82 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
84 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
85 buildPathToIdrefLeafNode());
87 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
88 .getFunction(null, null, "derived-from");
90 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
91 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a4"));
92 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b2"));
93 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-b3"));
94 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "id-b4"));
96 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a1"));
97 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a2"));
98 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b1"));
99 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-c1"));
100 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-c2"));
102 final Function derivedFromOrSelfFunction = normalizedNodeContextSupport.getFunctionContext()
103 .getFunction(null, null, "derived-from-or-self");
104 assertTrue(getDerivedFromResult(derivedFromOrSelfFunction, normalizedNodeContext, "bar-prefix:id-c2"));
108 public void testInvalidTypeOfCorrespondingSchemaNode() throws Exception {
109 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
110 "/yang-xpath-functions-test/derived-from-function/bar-invalid.yang");
111 assertNotNull(schemaContext);
113 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
114 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
116 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
117 converterBiMap.put("bar-prefix", barModule);
119 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
120 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
122 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
123 buildPathToIdrefLeafNode());
125 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
126 .getFunction(null, null, "derived-from");
128 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "some-identity"));
132 public void testInvalidNormalizedNodeValueType() throws Exception {
133 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
134 "/yang-xpath-functions-test/derived-from-function/foo.yang",
135 "/yang-xpath-functions-test/derived-from-function/bar.yang");
136 assertNotNull(schemaContext);
138 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
139 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode("should be QName"));
141 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
142 converterBiMap.put("bar-prefix", barModule);
144 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
145 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
147 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
148 buildPathToIdrefLeafNode());
150 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
151 .getFunction(null, null, "derived-from");
153 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
157 public void shouldFailOnUnknownPrefixOfIdentity() throws Exception {
158 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
159 "/yang-xpath-functions-test/derived-from-function/foo.yang",
160 "/yang-xpath-functions-test/derived-from-function/bar.yang");
161 assertNotNull(schemaContext);
163 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
164 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
166 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
167 converterBiMap.put("bar-prefix", barModule);
169 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
170 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
172 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
173 buildPathToIdrefLeafNode());
175 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
176 .getFunction(null, null, "derived-from");
179 getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "unknown-prefix:id-a3");
180 fail("Function call should have failed on unresolved prefix of the identity argument.");
181 } catch (IllegalArgumentException ex) {
182 assertEquals("Cannot resolve prefix 'unknown-prefix' from identity 'unknown-prefix:id-a3'.",
188 public void shouldFailOnMalformedIdentityArgument() throws Exception {
189 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
190 "/yang-xpath-functions-test/derived-from-function/foo.yang",
191 "/yang-xpath-functions-test/derived-from-function/bar.yang");
192 assertNotNull(schemaContext);
194 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
195 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
197 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
198 converterBiMap.put("bar-prefix", barModule);
200 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
201 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
203 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
204 buildPathToIdrefLeafNode());
206 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
207 .getFunction(null, null, "derived-from");
210 getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo:bar:id-a3");
211 fail("Function call should have failed on malformed identity argument.");
212 } catch (IllegalArgumentException ex) {
213 assertEquals("Malformed identity argument: foo:bar:id-a3.", ex.getMessage());
218 public void shouldFailOnUnknownIdentityArgument() throws Exception {
219 final SchemaContext schemaContext = YangParserTestUtils.parseYangResources(DerivedFromXPathFunctionTest.class,
220 "/yang-xpath-functions-test/derived-from-function/foo.yang",
221 "/yang-xpath-functions-test/derived-from-function/bar.yang");
222 assertNotNull(schemaContext);
224 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
225 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
227 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
228 converterBiMap.put("bar-prefix", barModule);
230 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
231 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
233 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
234 buildPathToIdrefLeafNode());
236 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
237 .getFunction(null, null, "derived-from");
240 getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a333");
241 fail("Function call should have failed on unknown identity argument.");
242 } catch (IllegalArgumentException ex) {
243 assertTrue(ex.getMessage().startsWith(
244 "Identity (foo-ns?revision=2017-04-03)id-a333 does not have a corresponding identity schema "
245 + "node in the module"));
250 public void shouldFailOnInvalidNumberOfArguments() throws Exception {
251 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
252 final Function derivedFromFunction = yangFunctionContext.getFunction(null, null, "derived-from");
254 final Context mockedContext = mock(Context.class);
257 derivedFromFunction.call(mockedContext, ImmutableList.of("some-identity", "should not be here"));
258 fail("Function call should have failed on invalid number of arguments.");
259 } catch (final FunctionCallException ex) {
260 assertEquals("derived-from() takes two arguments: node-set nodes, string identity.", ex.getMessage());
265 public void shouldFailOnInvalidTypeOfArgument() throws Exception {
266 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
267 final Function bitIsSetFunction = yangFunctionContext.getFunction(null, null, "derived-from");
269 final Context mockedContext = mock(Context.class);
272 bitIsSetFunction.call(mockedContext, ImmutableList.of(100));
273 fail("Function call should have failed on invalid type of the identity argument.");
274 } catch (final FunctionCallException ex) {
275 assertEquals("Argument 'identity' of derived-from() function should be a String.", ex.getMessage());
279 private static boolean getDerivedFromResult(final Function derivedFromFunction, final NormalizedNodeContext nnCtx,
280 final String identityArg) throws Exception {
281 return (boolean) derivedFromFunction.call(nnCtx, ImmutableList.of(identityArg));
284 private static ContainerNode buildMyContainerNode(final Object idrefLeafValue) {
285 final LeafNode<?> idrefLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(idrefLeaf))
286 .withValue(idrefLeafValue).build();
288 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
289 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
290 new NodeIdentifierWithPredicates(myList, keyLeaf, "key-value"))
291 .withChild(idrefLeafNode).build()).build();
293 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
294 new NodeIdentifier(myContainer)).withChild(myListNode).build();
295 return myContainerNode;
298 private static YangInstanceIdentifier buildPathToIdrefLeafNode() {
299 final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
300 final ImmutableMap<QName, Object> keys = builder.put(keyLeaf, "key-value").build();
302 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
303 .node(new NodeIdentifierWithPredicates(myList, keys)).node(idrefLeaf);