2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2023 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.spi.performance
23 import org.onap.cps.spi.CpsDataPersistenceService
24 import org.onap.cps.spi.impl.CpsPersistencePerfSpecBase
25 import org.springframework.beans.factory.annotation.Autowired
26 import org.springframework.test.context.jdbc.Sql
27 import org.springframework.util.StopWatch
29 class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase {
32 CpsDataPersistenceService objectUnderTest
34 def stopWatch = new StopWatch()
36 @Sql([CLEAR_DATA, PERF_TEST_DATA])
37 def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
38 when: 'a node with a large number of descendants is created'
40 createLineage(objectUnderTest, 150, 50, false)
42 def setupDurationInMillis = stopWatch.getTotalTimeMillis()
43 then: 'setup duration is under 10 seconds'
44 recordAndAssertPerformance('Setup', 10_000, setupDurationInMillis)
47 def 'Delete 5 children with grandchildren'() {
48 when: 'child nodes are deleted'
51 def childPath = "${PERF_TEST_PARENT}/perf-test-child-${it}".toString()
52 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
55 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
56 then: 'delete duration is under 300 milliseconds'
57 recordAndAssertPerformance('Delete 5 children', 300, deleteDurationInMillis)
60 def 'Batch delete 100 children with grandchildren'() {
61 given: 'a list of xpaths to delete'
62 def xpathsToDelete = (6..105).collect {
63 "${PERF_TEST_PARENT}/perf-test-child-${it}".toString()
65 when: 'child nodes are deleted'
67 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
69 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
70 then: 'delete duration is under 250 milliseconds'
71 recordAndAssertPerformance('Batch delete 100 children', 250, deleteDurationInMillis)
74 def 'Delete 50 grandchildren (that have no descendants)'() {
75 when: 'target nodes are deleted'
78 def grandchildPath = "${PERF_TEST_PARENT}/perf-test-child-106/perf-test-grand-child-${it}".toString()
79 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
82 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
83 then: 'delete duration is under 300 milliseconds'
84 recordAndAssertPerformance('Delete 50 grandchildren', 300, deleteDurationInMillis)
87 def 'Batch delete 500 grandchildren (that have no descendants)'() {
88 given: 'a list of xpaths to delete'
89 def xpathsToDelete = []
90 for (int childIndex = 0; childIndex < 10; childIndex++) {
91 xpathsToDelete.addAll((1..50).collect {
92 "${PERF_TEST_PARENT}/perf-test-child-${107+childIndex}/perf-test-grand-child-${it}".toString()
95 when: 'target nodes are deleted'
97 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
99 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
100 then: 'delete duration is under 125 milliseconds'
101 recordAndAssertPerformance('Batch delete 500 grandchildren', 125, deleteDurationInMillis)
104 @Sql([CLEAR_DATA, PERF_TEST_DATA])
105 def 'Create a node with many list elements (please note, subsequent tests depend on this running first).'() {
106 when: 'a node with a large number of lists is created'
108 createLineage(objectUnderTest, 150, 50, true)
110 def setupDurationInMillis = stopWatch.getTotalTimeMillis()
111 then: 'setup duration is under 10 seconds'
112 recordAndAssertPerformance('Setup lists', 10_000, setupDurationInMillis)
115 def 'Delete 5 whole lists'() {
116 when: 'lists are deleted'
119 def childPath = "${PERF_TEST_PARENT}/perf-test-list-${it}".toString()
120 objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
123 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
124 then: 'delete duration is under 1300 milliseconds'
125 recordAndAssertPerformance('Delete 5 whole lists', 1300, deleteDurationInMillis)
128 def 'Batch delete 100 whole lists'() {
129 given: 'a list of xpaths to delete'
130 def xpathsToDelete = (6..105).collect {
131 "${PERF_TEST_PARENT}/perf-test-list-${it}".toString()
133 when: 'lists are deleted'
135 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
137 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
138 then: 'delete duration is under 250 milliseconds'
139 recordAndAssertPerformance('Batch delete 100 whole lists', 250, deleteDurationInMillis)
142 def 'Delete 10 list elements'() {
143 when: 'list elements are deleted'
146 def grandchildPath = "${PERF_TEST_PARENT}/perf-test-list-106[@key='${it}']".toString()
147 objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
150 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
151 then: 'delete duration is under 600 milliseconds'
152 recordAndAssertPerformance('Delete 10 lists elements', 600, deleteDurationInMillis)
155 def 'Batch delete 500 list elements'() {
156 given: 'a list of xpaths to delete'
157 def xpathsToDelete = []
158 for (int childIndex = 0; childIndex < 10; childIndex++) {
159 xpathsToDelete.addAll((1..50).collect {
160 "${PERF_TEST_PARENT}/perf-test-list-${107+childIndex}[@key='${it}']".toString()
163 when: 'list elements are deleted'
165 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
167 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
168 then: 'delete duration is under 125 milliseconds'
169 recordAndAssertPerformance('Batch delete 500 lists elements', 125, deleteDurationInMillis)
172 @Sql([CLEAR_DATA, PERF_TEST_DATA])
173 def 'Delete 1 large data node'() {
174 given: 'a node with a large number of descendants is created'
175 createLineage(objectUnderTest, 50, 50, false)
176 createLineage(objectUnderTest, 50, 50, true)
177 when: 'parent node is deleted'
179 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, PERF_TEST_PARENT)
181 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
182 then: 'delete duration is under 300 milliseconds'
183 recordAndAssertPerformance('Delete one large node', 300, deleteDurationInMillis)
186 @Sql([CLEAR_DATA, PERF_TEST_DATA])
187 def 'Batch delete 1 large data node'() {
188 given: 'a node with a large number of descendants is created'
189 createLineage(objectUnderTest, 50, 50, false)
190 createLineage(objectUnderTest, 50, 50, true)
191 when: 'parent node is batch deleted'
193 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, [PERF_TEST_PARENT])
195 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
196 then: 'delete duration is under 250 milliseconds'
197 recordAndAssertPerformance('Batch delete one large node', 250, deleteDurationInMillis)
200 @Sql([CLEAR_DATA, PERF_TEST_DATA])
201 def 'Delete root node with many descendants'() {
202 given: 'a node with a large number of descendants is created'
203 createLineage(objectUnderTest, 50, 50, false)
204 createLineage(objectUnderTest, 50, 50, true)
205 when: 'root node is deleted'
207 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, '/')
209 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
210 then: 'delete duration is under 300 milliseconds'
211 recordAndAssertPerformance('Delete root node', 300, deleteDurationInMillis)
214 @Sql([CLEAR_DATA, PERF_TEST_DATA])
215 def 'Delete data nodes for an anchor'() {
216 given: 'a node with a large number of descendants is created'
217 createLineage(objectUnderTest, 50, 50, false)
218 createLineage(objectUnderTest, 50, 50, true)
219 when: 'data nodes are deleted'
221 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR)
223 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
224 then: 'delete duration is under 300 milliseconds'
225 recordAndAssertPerformance('Delete data nodes for anchor', 300, deleteDurationInMillis)
228 @Sql([CLEAR_DATA, PERF_TEST_DATA])
229 def 'Delete data nodes for multiple anchors'() {
230 given: 'a node with a large number of descendants is created'
231 createLineage(objectUnderTest, 50, 50, false)
232 createLineage(objectUnderTest, 50, 50, true)
233 when: 'data nodes are deleted'
235 objectUnderTest.deleteDataNodes(PERF_DATASPACE, [PERF_ANCHOR])
237 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
238 then: 'delete duration is under 250 milliseconds'
239 recordAndAssertPerformance('Delete data nodes for anchors', 250, deleteDurationInMillis)