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.parseYangSources(ImmutableList.of(
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.parseYangSource(
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.parseYangSources(ImmutableList.of(
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.parseYangSources(ImmutableList.of(
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'.", ex.getMessage());
189 public void shouldFailOnMalformedIdentityArgument() throws Exception {
190 final SchemaContext schemaContext = YangParserTestUtils.parseYangSources(ImmutableList.of(
191 "/yang-xpath-functions-test/derived-from-function/foo.yang",
192 "/yang-xpath-functions-test/derived-from-function/bar.yang"));
193 assertNotNull(schemaContext);
195 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
196 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
198 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
199 converterBiMap.put("bar-prefix", barModule);
201 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
202 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
204 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
205 buildPathToIdrefLeafNode());
207 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
208 .getFunction(null, null, "derived-from");
211 getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo:bar:id-a3");
212 fail("Function call should have failed on malformed identity argument.");
213 } catch (IllegalArgumentException ex) {
214 assertEquals("Malformed identity argument: foo:bar:id-a3.", ex.getMessage());
219 public void shouldFailOnUnknownIdentityArgument() throws Exception {
220 final SchemaContext schemaContext = YangParserTestUtils.parseYangSources(ImmutableList.of(
221 "/yang-xpath-functions-test/derived-from-function/foo.yang",
222 "/yang-xpath-functions-test/derived-from-function/bar.yang"));
223 assertNotNull(schemaContext);
225 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
226 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNode(idC2Identity));
228 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
229 converterBiMap.put("bar-prefix", barModule);
231 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
232 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
234 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
235 buildPathToIdrefLeafNode());
237 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
238 .getFunction(null, null, "derived-from");
241 getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a333");
242 fail("Function call should have failed on unknown identity argument.");
243 } catch (IllegalArgumentException ex) {
244 assertTrue(ex.getMessage().startsWith(
245 "Identity (foo-ns?revision=2017-04-03)id-a333 does not have a corresponding identity schema " +
246 "node in the module"));
251 public void shouldFailOnInvalidNumberOfArguments() throws Exception {
252 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
253 final Function derivedFromFunction = yangFunctionContext.getFunction(null, null, "derived-from");
255 final Context mockedContext = mock(Context.class);
258 derivedFromFunction.call(mockedContext, ImmutableList.of("some-identity", "should not be here"));
259 fail("Function call should have failed on invalid number of arguments.");
260 } catch (final FunctionCallException ex) {
261 assertEquals("derived-from() takes two arguments: node-set nodes, string identity.", ex.getMessage());
266 public void shouldFailOnInvalidTypeOfArgument() throws Exception {
267 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
268 final Function bitIsSetFunction = yangFunctionContext.getFunction(null, null, "derived-from");
270 final Context mockedContext = mock(Context.class);
273 bitIsSetFunction.call(mockedContext, ImmutableList.of(100));
274 fail("Function call should have failed on invalid type of the identity argument.");
275 } catch (final FunctionCallException ex) {
276 assertEquals("Argument 'identity' of derived-from() function should be a String.", ex.getMessage());
280 private static boolean getDerivedFromResult(final Function derivedFromFunction, final NormalizedNodeContext nnCtx,
281 final String identityArg) throws Exception {
282 return (boolean) derivedFromFunction.call(nnCtx, ImmutableList.of(identityArg));
285 private static ContainerNode buildMyContainerNode(final Object idrefLeafValue) {
286 final LeafNode<?> idrefLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(idrefLeaf))
287 .withValue(idrefLeafValue).build();
289 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
290 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
291 new NodeIdentifierWithPredicates(myList, keyLeaf, "key-value"))
292 .withChild(idrefLeafNode).build()).build();
294 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
295 new NodeIdentifier(myContainer)).withChild(myListNode).build();
296 return myContainerNode;
299 private static YangInstanceIdentifier buildPathToIdrefLeafNode() {
300 final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
301 final ImmutableMap<QName, Object> keys = builder.put(keyLeaf, "key-value").build();
303 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
304 .node(new NodeIdentifierWithPredicates(myList, keys)).node(idrefLeaf);