2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2022 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.cpspath.parser
23 import org.springframework.util.StopWatch
24 import spock.lang.Specification
26 class CpsPathUtilSpec extends Specification {
28 def 'Normalized xpaths for list index values using #scenario'() {
29 when: 'xpath with #scenario is parsed'
30 def result = CpsPathUtil.getNormalizedXpath(xpath)
31 then: 'normalized path uses single quotes for leave values'
32 assert result == "/parent/child[@common-leaf-name='123']"
33 where: 'the following xpaths are used'
35 'no quotes' | '/parent/child[@common-leaf-name=123]'
36 'double quotes' | '/parent/child[@common-leaf-name="123"]'
37 'single quotes' | "/parent/child[@common-leaf-name='123']"
40 def 'Normalized parent xpaths'() {
41 when: 'a given xpath with #scenario is parsed'
42 def result = CpsPathUtil.getNormalizedParentXpath(xpath)
43 then: 'the result is the expected parent path'
44 assert result == expectedParentPath
45 where: 'the following xpaths are used'
46 scenario | xpath || expectedParentPath
47 'no child' | '/parent' || ''
48 'child and parent' | '/parent/child' || '/parent'
49 'grand child' | '/parent/child/grandChild' || '/parent/child'
50 'parent & top is list element' | '/parent[@id=1]/child' || "/parent[@id='1']"
51 'parent is list element' | '/parent/child[@id=1]/grandChild' || "/parent/child[@id='1']"
52 'parent is list element with /' | "/parent/child[@id='a/b']/grandChild" || "/parent/child[@id='a/b']"
53 'parent is list element with [' | "/parent/child[@id='a[b']/grandChild" || "/parent/child[@id='a[b']"
54 'parent is list element using "' | '/parent/child[@id="x"]/grandChild' || "/parent/child[@id='x']"
57 def 'Get node ID sequence for given xpath'() {
58 when: 'a given xpath with #scenario is parsed'
59 def result = CpsPathUtil.getXpathNodeIdSequence(xpath)
60 then: 'the result is the expected node ID sequence'
61 assert result == expectedNodeIdSequence
62 where: 'the following xpaths are used'
63 scenario | xpath || expectedNodeIdSequence
64 'no child' | '/parent' || ["parent"]
65 'child and parent' | '/parent/child' || ["parent","child"]
66 'grand child' | '/parent/child/grandChild' || ["parent","child","grandChild"]
67 'parent & top is list element' | '/parent[@id=1]/child' || ["parent","child"]
68 'parent is list element' | '/parent/child[@id=1]/grandChild' || ["parent","child","grandChild"]
69 'parent is list element with /' | "/parent/child[@id='a/b']/grandChild" || ["parent","child","grandChild"]
70 'parent is list element with [' | "/parent/child[@id='a[b']/grandChild" || ["parent","child","grandChild"]
73 def 'Recognizing (absolute) xpaths to List elements'() {
74 expect: 'check for list returns the correct values'
75 assert CpsPathUtil.isPathToListElement(xpath) == expectList
76 where: 'the following xpaths are used'
78 '/parent[@id=1]' || true
79 '/parent[@id=1]/child' || false
80 '/parent/child[@id=1]' || true
81 '//child[@id=1]' || false
84 def 'Parsing Exception'() {
85 when: 'a invalid xpath is parsed'
86 CpsPathUtil.getNormalizedXpath('///')
87 then: 'a path parsing exception is thrown'
88 thrown(PathParsingException)
91 def 'CPS Path Processing Performance Test.'() {
92 when: '200,000 paths are processed'
93 def stopWatch = new StopWatch()
96 CpsPathUtil.getNormalizedXpath('/long/path/to/see/if/it/adds/paring/time/significantly/parent/child[@common-leaf-name="123"]')
97 CpsPathUtil.getNormalizedXpath('//child[@other-leaf=1]/leaf-name[text()="search"]/ancestor::parent')
100 then: 'it takes less then 10,000 milliseconds'
101 // In CI this actually takes about 3-5 sec which is approx. 50+ parser executions per millisecond!
102 assert stopWatch.getTotalTimeMillis() < 10000