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.assertSame;
15 import static org.junit.Assert.assertTrue;
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.ImmutableSet;
23 import com.google.common.collect.Maps;
27 import org.jaxen.Context;
28 import org.jaxen.Function;
29 import org.junit.BeforeClass;
30 import org.junit.Test;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.common.QNameModule;
33 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
37 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
42 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathSchemaContext;
43 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
44 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
45 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47 public class YangXPathFunctionsTest {
49 private static JaxenSchemaContextFactory jaxenSchemaContextFactory;
52 public static void setup() {
53 jaxenSchemaContextFactory = new JaxenSchemaContextFactory();
57 public void testRematchFunction() throws Exception {
58 // re-match() uses regex processing from yang-parser-impl which has been thoroughly tested within
59 // the Bug5410Test unit test class, so here is just a basic test
60 final YangFunctionContext yangFunctionContext = YangFunctionContext.getInstance();
61 final Function rematchFunction = yangFunctionContext.getFunction(null, null, "re-match");
63 final Context mockedContext = mock(Context.class);
65 boolean rematchResult = (boolean) rematchFunction.call(mockedContext, ImmutableList.of("abbc", "[abc]{1,4}"));
66 assertTrue(rematchResult);
67 rematchResult = (boolean) rematchFunction.call(mockedContext, ImmutableList.of("abbcc", "[abc]{1,4}"));
68 assertFalse(rematchResult);
72 public void testDerefFunctionForInstanceIdentifier() throws Exception {
73 final QNameModule fooModule = QNameModule.create(URI.create("foo-ns"),
74 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
75 final QName myContainer = QName.create(fooModule, "my-container");
76 final QName myList = QName.create(fooModule, "my-list");
77 final QName keyLeafA = QName.create(fooModule, "key-leaf-a");
78 final QName keyLeafB = QName.create(fooModule, "key-leaf-b");
79 final QName iidLeaf = QName.create(fooModule, "iid-leaf");
80 final QName referencedLeaf = QName.create(fooModule, "referenced-leaf");
82 final Map<QName, Object> keyValues = ImmutableMap.of(keyLeafA, "key-value-a", keyLeafB, "key-value-b");
83 final YangInstanceIdentifier iidPath = YangInstanceIdentifier.of(myContainer).node(myList)
84 .node(new NodeIdentifierWithPredicates(myList, keyValues)).node(referencedLeaf);
86 final LeafNode<?> iidLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(iidLeaf))
87 .withValue(iidPath).build();
88 final LeafNode<?> referencedLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(referencedLeaf))
89 .withValue("referenced-leaf-node-value").build();
91 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
92 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
93 new NodeIdentifierWithPredicates(myList, keyValues))
94 .withChild(iidLeafNode)
95 .withChild(referencedLeafNode).build())
98 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
99 new NodeIdentifier(myContainer)).withChild(myListNode).build();
101 final SchemaContext schemaContext = YangParserTestUtils.parseYangSource(
102 "/yang-xpath-functions-test/deref-function-iid/foo.yang");
103 assertNotNull(schemaContext);
105 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
106 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(myContainerNode);
108 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
109 converterBiMap.put("foo-prefix", fooModule);
111 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
112 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
114 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
115 .node(new NodeIdentifierWithPredicates(myList, keyValues)).node(iidLeaf);
116 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(path);
118 final Function derefFunction = normalizedNodeContextSupport.getFunctionContext()
119 .getFunction(null, null, "deref");
120 final Object derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
121 assertNotNull(derefResult);
122 assertTrue(derefResult instanceof NormalizedNode<?, ?>);
123 assertSame(referencedLeafNode, derefResult);
127 public void testDerefFunctionForLeafref() throws Exception {
128 final QNameModule fooModule = QNameModule.create(URI.create("foo-ns"),
129 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
130 final QName myContainer = QName.create(fooModule, "my-container");
131 final QName myInnerContainer = QName.create(fooModule, "my-inner-container");
132 final QName myList = QName.create(fooModule, "my-list");
133 final QName keyLeafA = QName.create(fooModule, "key-leaf-a");
134 final QName keyLeafB = QName.create(fooModule, "key-leaf-b");
135 final QName absLeafrefLeaf = QName.create(fooModule, "abs-leafref-leaf");
136 final QName relLeafrefLeaf = QName.create(fooModule, "rel-leafref-leaf");
137 final QName ordinaryLeafA = QName.create(fooModule, "ordinary-leaf-a");
138 final QName ordinaryLeafB = QName.create(fooModule, "ordinary-leaf-b");
139 final QName referencedLeaf = QName.create(fooModule, "referenced-leaf");
141 final Map<QName, Object> keyValues = ImmutableMap.of(keyLeafA, "value-a", keyLeafB, "value-b");
143 final LeafNode<?> absLeafrefNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(absLeafrefLeaf))
144 .withValue("referenced-leaf-node-value").build();
145 final LeafNode<?> relLeafrefNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(relLeafrefLeaf))
146 .withValue("referenced-leaf-node-value").build();
147 final LeafNode<?> ordinaryLeafANode = Builders.leafBuilder().withNodeIdentifier(
148 new NodeIdentifier(ordinaryLeafA)).withValue("value-a").build();
149 final LeafNode<?> ordinaryLeafBNode = Builders.leafBuilder().withNodeIdentifier(
150 new NodeIdentifier(ordinaryLeafB)).withValue("value-b").build();
152 final LeafNode<?> referencedLeafNode = Builders.leafBuilder().withNodeIdentifier(
153 new NodeIdentifier(referencedLeaf)).withValue("referenced-leaf-node-value").build();
155 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
156 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
157 new NodeIdentifierWithPredicates(myList, keyValues))
158 .withChild(referencedLeafNode).build())
161 final ContainerNode myInnerContainerNode = Builders.containerBuilder().withNodeIdentifier(
162 new NodeIdentifier(myInnerContainer))
163 .withChild(absLeafrefNode)
164 .withChild(relLeafrefNode)
165 .withChild(ordinaryLeafANode)
166 .withChild(ordinaryLeafBNode).build();
168 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
169 new NodeIdentifier(myContainer))
170 .withChild(myListNode)
171 .withChild(myInnerContainerNode).build();
173 final SchemaContext schemaContext = YangParserTestUtils.parseYangSource(
174 "/yang-xpath-functions-test/deref-function-leafref/foo.yang");
175 assertNotNull(schemaContext);
177 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
178 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(myContainerNode);
180 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
181 converterBiMap.put("foo-prefix", fooModule);
183 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
184 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
186 final YangInstanceIdentifier absLeafrefPath = YangInstanceIdentifier.of(myInnerContainer).node(absLeafrefLeaf);
187 NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(absLeafrefPath);
189 final Function derefFunction = normalizedNodeContextSupport.getFunctionContext()
190 .getFunction(null, null, "deref");
191 Object derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
192 assertNotNull(derefResult);
193 assertTrue(derefResult instanceof NormalizedNode<?, ?>);
194 assertSame(referencedLeafNode, derefResult);
196 final YangInstanceIdentifier relLeafrefPath = YangInstanceIdentifier.of(myInnerContainer).node(relLeafrefLeaf);
197 normalizedNodeContext = normalizedNodeContextSupport.createContext(relLeafrefPath);
199 derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
200 assertNotNull(derefResult);
201 assertTrue(derefResult instanceof NormalizedNode<?, ?>);
202 assertSame(referencedLeafNode, derefResult);
206 public void testDerivedFromFunction() throws Exception {
207 // also includes test for derived-from-or-self function
208 final QNameModule barModule = QNameModule.create(URI.create("bar-ns"),
209 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
210 final QName myContainer = QName.create(barModule, "my-container");
211 final QName myList = QName.create(barModule, "my-list");
212 final QName keyLeaf = QName.create(barModule, "key-leaf");
213 final QName idrefLeaf = QName.create(barModule, "idref-leaf");
214 final QName idC2Identity = QName.create(barModule, "id-c2");
216 final LeafNode<?> idrefLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(idrefLeaf))
217 .withValue(idC2Identity).build();
219 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
220 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
221 new NodeIdentifierWithPredicates(myList, keyLeaf, "key-value"))
222 .withChild(idrefLeafNode).build()).build();
224 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
225 new NodeIdentifier(myContainer)).withChild(myListNode).build();
227 final SchemaContext schemaContext = YangParserTestUtils.parseYangSources(
228 "/yang-xpath-functions-test/derived-from-function");
229 assertNotNull(schemaContext);
231 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
232 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(myContainerNode);
234 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
235 converterBiMap.put("bar-prefix", barModule);
237 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
238 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
240 final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
241 final ImmutableMap<QName, Object> keys = builder.put(keyLeaf, "key-value").build();
243 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
244 .node(new NodeIdentifierWithPredicates(myList, keys)).node(idrefLeaf);
245 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(path);
247 final Function derivedFromFunction = normalizedNodeContextSupport.getFunctionContext()
248 .getFunction(null, null, "derived-from");
250 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a3"));
251 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a4"));
252 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b2"));
253 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-b3"));
254 assertTrue(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "id-b4"));
256 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a1"));
257 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-a2"));
258 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-b1"));
259 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "foo-prefix:id-c1"));
260 assertFalse(getDerivedFromResult(derivedFromFunction, normalizedNodeContext, "bar-prefix:id-c2"));
262 final Function derivedFromOrSelfFunction = normalizedNodeContextSupport.getFunctionContext()
263 .getFunction(null, null, "derived-from-or-self");
264 assertTrue(getDerivedFromResult(derivedFromOrSelfFunction, normalizedNodeContext, "bar-prefix:id-c2"));
270 public void testEnumValueFunction() throws Exception {
271 final QNameModule fooModule = QNameModule.create(URI.create("foo-ns"),
272 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
273 final QName myContainer = QName.create(fooModule, "my-container");
274 final QName alarm = QName.create(fooModule, "alarm");
275 final QName severity = QName.create(fooModule, "severity");
276 final QName ordinaryLeaf = QName.create(fooModule, "ordinary-leaf");
278 final LeafNode<?> ordinaryLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(ordinaryLeaf))
279 .withValue("test-value").build();
281 final MapNode alarmListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(alarm))
282 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
283 new NodeIdentifierWithPredicates(alarm, severity, "major"))
284 .withChild(ordinaryLeafNode).build()).build();
286 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
287 new NodeIdentifier(myContainer)).withChild(alarmListNode).build();
289 final SchemaContext schemaContext = YangParserTestUtils.parseYangSource(
290 "/yang-xpath-functions-test/enum-value-function/foo.yang");
291 assertNotNull(schemaContext);
293 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
294 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(myContainerNode);
296 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
297 converterBiMap.put("foo-prefix", fooModule);
299 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
300 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
302 final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
303 final ImmutableMap<QName, Object> keys = builder.put(severity, "major").build();
305 final YangInstanceIdentifier path = YangInstanceIdentifier.of(alarm)
306 .node(new NodeIdentifierWithPredicates(alarm, keys)).node(severity);
307 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(path);
309 final Function enumValueFunction = normalizedNodeContextSupport.getFunctionContext()
310 .getFunction(null, null, "enum-value");
311 final int enumValueResult = (int) enumValueFunction.call(normalizedNodeContext, ImmutableList.of());
312 assertEquals(5, enumValueResult);
316 public void testBitIsSetFunction() throws Exception {
317 final QNameModule fooModule = QNameModule.create(URI.create("foo-ns"),
318 SimpleDateFormatUtil.getRevisionFormat().parse("2017-04-03"));
319 final QName myContainer = QName.create(fooModule, "my-container");
320 final QName myList = QName.create(fooModule, "my-list");
321 final QName flags = QName.create(fooModule, "flags");
322 final QName ordinaryLeaf = QName.create(fooModule, "ordinary-leaf");
324 final LeafNode<?> ordinaryLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(ordinaryLeaf))
325 .withValue("test-value").build();
327 final Set<String> setOfBits = ImmutableSet.of("UP", "PROMISCUOUS");
329 final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myList))
330 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
331 new NodeIdentifierWithPredicates(myList, flags, setOfBits))
332 .withChild(ordinaryLeafNode).build()).build();
334 final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
335 new NodeIdentifier(myContainer)).withChild(myListNode).build();
337 final SchemaContext schemaContext = YangParserTestUtils.parseYangSource(
338 "/yang-xpath-functions-test/bit-is-set-function/foo.yang");
339 assertNotNull(schemaContext);
341 final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
342 final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(myContainerNode);
344 final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
345 converterBiMap.put("foo-prefix", fooModule);
347 final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
348 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
350 final ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
351 final ImmutableMap<QName, Object> keys = builder.put(flags, setOfBits).build();
353 final YangInstanceIdentifier path = YangInstanceIdentifier.of(myList)
354 .node(new NodeIdentifierWithPredicates(myList, keys)).node(flags);
355 final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(path);
357 final Function bitIsSetFunction = normalizedNodeContextSupport.getFunctionContext()
358 .getFunction(null, null, "bit-is-set");
359 boolean bitIsSetResult = (boolean) bitIsSetFunction.call(normalizedNodeContext, ImmutableList.of("UP"));
360 assertTrue(bitIsSetResult);
361 bitIsSetResult = (boolean) bitIsSetFunction.call(normalizedNodeContext, ImmutableList.of("PROMISCUOUS"));
362 assertTrue(bitIsSetResult);
363 bitIsSetResult = (boolean) bitIsSetFunction.call(normalizedNodeContext, ImmutableList.of("DISABLED"));
364 assertFalse(bitIsSetResult);
367 private static boolean getDerivedFromResult(final Function derivedFromFunction, final NormalizedNodeContext nnCtx,
368 final String identityArg) throws Exception {
369 return (boolean) derivedFromFunction.call(nnCtx, ImmutableList.of(identityArg));