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 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;
45 public class DerivedFromXPathFunctionTest {
47 private static JaxenSchemaContextFactory jaxenSchemaContextFactory;
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;
57 public static void setup() throws ParseException {
58 jaxenSchemaContextFactory = new JaxenSchemaContextFactory();
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");
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);
77 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
78 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
80 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
81 converterBiMap.put("bar-prefix", barModule);
83 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
84 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
86 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
87 buildPathToIdrefLeafNode());
89 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
90 .getFunction(null, null, "derived-from");
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"));
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"));
104 final Function derivedFromOrSelfFunction = normalizedNodeContextSupport.getFunctionContext()
105 .getFunction(null, null, "derived-from-or-self");
106 assertTrue(getDerivedFromResult(derivedFromOrSelfFunction, normalizedNodeContext, "bar-prefix:id-c2"));
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);
115 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
116 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
118 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
119 converterBiMap.put("bar-prefix", barModule);
121 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
122 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
124 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
125 buildPathToIdrefLeafNode());
127 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
128 .getFunction(null, null, "derived-from");
130 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "some-identity"));
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);
140 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
141 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode("should be QName"));
143 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
144 converterBiMap.put("bar-prefix", barModule);
146 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
147 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
149 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
150 buildPathToIdrefLeafNode());
152 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
153 .getFunction(null, null, "derived-from");
155 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
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);
165 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
166 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
168 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
169 converterBiMap.put("bar-prefix", barModule);
171 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
172 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
174 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
175 buildPathToIdrefLeafNode());
177 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
178 .getFunction(null, null, "derived-from");
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'.",
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);
196 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
197 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
199 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
200 converterBiMap.put("bar-prefix", barModule);
202 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
203 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
205 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
206 buildPathToIdrefLeafNode());
208 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
209 .getFunction(null, null, "derived-from");
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());
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);
226 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
227 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
229 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
230 converterBiMap.put("bar-prefix", barModule);
232 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
233 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
235 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
236 buildPathToIdrefLeafNode());
238 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
239 .getFunction(null, null, "derived-from");
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"));
252 public void shouldFailOnInvalidNumberOfArguments() throws Exception {
253 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
254 final Function derivedFromFunction = yangFunctionContext.getFunction(null, null, "derived-from");
256 final Context mockedContext = mock(Context.class);
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());
267 public void shouldFailOnInvalidTypeOfArgument() throws Exception {
268 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
269 final Function bitIsSetFunction = yangFunctionContext.getFunction(null, null, "derived-from");
271 final Context mockedContext = mock(Context.class);
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());
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));
286 private static ContainerNode buildMyContainerNode(final Object idrefLeafValue) {
287 final LeafNode<?> idrefLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(idrefLeaf))
288 .withValue(idrefLeafValue).build();
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();
295 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
296 new NodeIdentifier(myContainer)).withChild(myListNode).build();
297 return myContainerNode;
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();
304 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
305 .node(new NodeIdentifierWithPredicates(myList, keys)).node(idrefLeaf);