Enhance read performance tests
[cps.git] / cps-ri / src / test / groovy / org / onap / cps / spi / performance / CpsToDataNodePerfTest.groovy
1 /*
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.spi.performance
22
23 import org.apache.commons.lang3.time.StopWatch
24 import org.onap.cps.spi.CpsDataPersistenceService
25 import org.onap.cps.spi.impl.CpsPersistenceSpecBase
26 import org.onap.cps.spi.model.DataNode
27 import org.onap.cps.spi.model.DataNodeBuilder
28 import org.springframework.beans.factory.annotation.Autowired
29 import org.springframework.test.context.jdbc.Sql
30 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
31
32 class CpsToDataNodePerfTest extends CpsPersistenceSpecBase {
33
34     static final String PERF_TEST_DATA = '/data/perf-test.sql'
35
36     @Autowired
37     CpsDataPersistenceService objectUnderTest
38
39     def PERF_TEST_PARENT = '/perf-parent-1'
40
41     def EXPECTED_NUMBER_OF_NODES = 10051  //  1 Parent + 50 Children + 10000 Grand-children
42
43     @Sql([CLEAR_DATA, PERF_TEST_DATA])
44     def 'Get data node by xpath with all descendants with many children'() {
45         given: 'nodes and grandchildren have been persisted'
46             def setupStopWatch = new StopWatch()
47             setupStopWatch.start()
48             createLineage()
49             setupStopWatch.stop()
50             def setupDurationInMillis = setupStopWatch.getTime()
51         and: 'setup duration is under 8000 milliseconds'
52             assert setupDurationInMillis < 8000
53         when: 'get parent is executed with all descendants'
54             def readStopWatch = new StopWatch()
55             readStopWatch.start()
56             def result = objectUnderTest.getDataNode('PERF-DATASPACE', 'PERF-ANCHOR', PERF_TEST_PARENT, INCLUDE_ALL_DESCENDANTS)
57             readStopWatch.stop()
58             def readDurationInMillis = readStopWatch.getTime()
59         then: 'read duration is under 450 milliseconds'
60             assert readDurationInMillis < 450
61         and: 'data node is returned with all the descendants populated'
62             assert countDataNodes(result) == EXPECTED_NUMBER_OF_NODES
63         when: 'get root is executed with all descendants'
64             readStopWatch.reset()
65             readStopWatch.start()
66             result = objectUnderTest.getDataNode('PERF-DATASPACE', 'PERF-ANCHOR', '', INCLUDE_ALL_DESCENDANTS)
67             readStopWatch.stop()
68             readDurationInMillis = readStopWatch.getTime()
69         then: 'read duration is under 450 milliseconds'
70             assert readDurationInMillis < 450
71         and: 'data node is returned with all the descendants populated'
72             assert countDataNodes(result) == EXPECTED_NUMBER_OF_NODES
73         when: 'query is executed with all descendants'
74             readStopWatch.reset()
75             readStopWatch.start()
76             result = objectUnderTest.queryDataNodes('PERF-DATASPACE', 'PERF-ANCHOR', '//perf-parent-1', INCLUDE_ALL_DESCENDANTS)
77             readStopWatch.stop()
78             readDurationInMillis = readStopWatch.getTime()
79         then: 'read duration is under 450 milliseconds'
80             assert readDurationInMillis < 450
81         and: 'data node is returned with all the descendants populated'
82             assert countDataNodes(result) == EXPECTED_NUMBER_OF_NODES
83     }
84
85     def createLineage() {
86         def numOfChildren = 50
87         def numOfGrandChildren = 200
88         (1..numOfChildren).each {
89             def childName = "perf-test-child-${it}".toString()
90             def newChild = goForthAndMultiply(PERF_TEST_PARENT, childName, numOfGrandChildren)
91             objectUnderTest.addChildDataNode('PERF-DATASPACE', 'PERF-ANCHOR', PERF_TEST_PARENT, newChild)
92         }
93     }
94
95     def goForthAndMultiply(parentXpath, childName, numOfGrandChildren) {
96         def children = []
97         (1..numOfGrandChildren).each {
98             def child = new DataNodeBuilder().withXpath("${parentXpath}/${childName}/${it}perf-test-grand-child").build()
99             children.add(child)
100         }
101         return new DataNodeBuilder().withXpath("${parentXpath}/${childName}").withChildDataNodes(children).build()
102     }
103
104     def countDataNodes(dataNodes) {
105         int nodeCount = 1
106         for (DataNode parent : dataNodes) {
107             for (DataNode child : parent.childDataNodes) {
108                 nodeCount = nodeCount + (countDataNodes(child))
109             }
110         }
111         return nodeCount
112     }
113 }