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
28 class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase {
31 CpsDataPersistenceService objectUnderTest
33 @Sql([CLEAR_DATA, PERF_TEST_DATA])
34 def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
35 when: 'a node with a large number of descendants is created'
37 createLineage(objectUnderTest, 150, 50, false)
39 def setupDurationInMillis = stopWatch.getTotalTimeMillis()
40 then: 'setup duration is under 10 seconds'
41 recordAndAssertPerformance('Setup', 10_000, setupDurationInMillis)
44 def 'Delete 5 children with grandchildren'() {
45 when: 'child nodes are deleted'
48 def childPath = "${PERF_TEST_PARENT}/perf-test-child-${it}".toString()
49 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
52 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
53 then: 'delete duration is under 150 milliseconds'
54 recordAndAssertPerformance('Delete 5 children', 150, deleteDurationInMillis)
57 def 'Batch delete 100 children with grandchildren'() {
58 given: 'a list of xpaths to delete'
59 def xpathsToDelete = (6..105).collect {
60 "${PERF_TEST_PARENT}/perf-test-child-${it}".toString()
62 when: 'child nodes are deleted'
64 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
66 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
67 then: 'delete duration is under 250 milliseconds'
68 recordAndAssertPerformance('Batch delete 100 children', 250, deleteDurationInMillis)
71 def 'Delete 50 grandchildren (that have no descendants)'() {
72 when: 'target nodes are deleted'
75 def grandchildPath = "${PERF_TEST_PARENT}/perf-test-child-106/perf-test-grand-child-${it}".toString()
76 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
79 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
80 then: 'delete duration is under 600 milliseconds'
81 recordAndAssertPerformance('Delete 50 grandchildren', 600, deleteDurationInMillis)
84 def 'Batch delete 500 grandchildren (that have no descendants)'() {
85 given: 'a list of xpaths to delete'
86 def xpathsToDelete = []
87 for (int childIndex = 0; childIndex < 10; childIndex++) {
88 xpathsToDelete.addAll((1..50).collect {
89 "${PERF_TEST_PARENT}/perf-test-child-${107+childIndex}/perf-test-grand-child-${it}".toString()
92 when: 'target nodes are deleted'
94 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
96 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
97 then: 'delete duration is under 100 milliseconds'
98 recordAndAssertPerformance('Batch delete 500 grandchildren', 100, deleteDurationInMillis)
101 @Sql([CLEAR_DATA, PERF_TEST_DATA])
102 def 'Create a node with many list elements (please note, subsequent tests depend on this running first).'() {
103 when: 'a node with a large number of lists is created'
105 createLineage(objectUnderTest, 150, 50, true)
107 def setupDurationInMillis = stopWatch.getTotalTimeMillis()
108 then: 'setup duration is under 6 seconds'
109 recordAndAssertPerformance('Setup lists', 6_000, setupDurationInMillis)
112 def 'Delete 5 whole lists'() {
113 when: 'lists are deleted'
116 def childPath = "${PERF_TEST_PARENT}/perf-test-list-${it}".toString()
117 objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
120 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
121 then: 'delete duration is under 130 milliseconds'
122 recordAndAssertPerformance('Delete 5 whole lists', 130, deleteDurationInMillis)
125 def 'Batch delete 100 whole lists'() {
126 given: 'a list of xpaths to delete'
127 def xpathsToDelete = (6..105).collect {
128 "${PERF_TEST_PARENT}/perf-test-list-${it}".toString()
130 when: 'lists are deleted'
132 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
134 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
135 then: 'delete duration is under 600 milliseconds'
136 recordAndAssertPerformance('Batch delete 100 whole lists', 600, deleteDurationInMillis)
139 def 'Delete 10 list elements'() {
140 when: 'list elements are deleted'
143 def grandchildPath = "${PERF_TEST_PARENT}/perf-test-list-106[@key='${it}']".toString()
144 objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
147 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
148 then: 'delete duration is under 180 milliseconds'
149 recordAndAssertPerformance('Delete 10 lists elements', 180, deleteDurationInMillis)
152 def 'Batch delete 500 list elements'() {
153 given: 'a list of xpaths to delete'
154 def xpathsToDelete = []
155 for (int childIndex = 0; childIndex < 10; childIndex++) {
156 xpathsToDelete.addAll((1..50).collect {
157 "${PERF_TEST_PARENT}/perf-test-list-${107+childIndex}[@key='${it}']".toString()
160 when: 'list elements are deleted'
162 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
164 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
165 then: 'delete duration is under 70 milliseconds'
166 recordAndAssertPerformance('Batch delete 500 lists elements', 70, deleteDurationInMillis)
169 @Sql([CLEAR_DATA, PERF_TEST_DATA])
170 def 'Delete 1 large data node'() {
171 given: 'a node with a large number of descendants is created'
172 createLineage(objectUnderTest, 50, 50, false)
173 createLineage(objectUnderTest, 50, 50, true)
174 when: 'parent node is deleted'
176 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, PERF_TEST_PARENT)
178 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
179 then: 'delete duration is under 220 milliseconds'
180 recordAndAssertPerformance('Delete one large node', 220, deleteDurationInMillis)
183 @Sql([CLEAR_DATA, PERF_TEST_DATA])
184 def 'Batch delete 1 large data node'() {
185 given: 'a node with a large number of descendants is created'
186 createLineage(objectUnderTest, 50, 50, false)
187 createLineage(objectUnderTest, 50, 50, true)
188 when: 'parent node is batch deleted'
190 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, [PERF_TEST_PARENT])
192 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
193 then: 'delete duration is under 220 milliseconds'
194 recordAndAssertPerformance('Batch delete one large node', 220, deleteDurationInMillis)
197 @Sql([CLEAR_DATA, PERF_TEST_DATA])
198 def 'Delete root node with many descendants'() {
199 given: 'a node with a large number of descendants is created'
200 createLineage(objectUnderTest, 50, 50, false)
201 createLineage(objectUnderTest, 50, 50, true)
202 when: 'root node is deleted'
204 objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, '/')
206 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
207 then: 'delete duration is under 300 milliseconds'
208 recordAndAssertPerformance('Delete root node', 300, deleteDurationInMillis)
211 @Sql([CLEAR_DATA, PERF_TEST_DATA])
212 def 'Delete data nodes for an anchor'() {
213 given: 'a node with a large number of descendants is created'
214 createLineage(objectUnderTest, 50, 50, false)
215 createLineage(objectUnderTest, 50, 50, true)
216 when: 'data nodes are deleted'
218 objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR)
220 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
221 then: 'delete duration is under 300 milliseconds'
222 recordAndAssertPerformance('Delete data nodes for anchor', 300, deleteDurationInMillis)
225 @Sql([CLEAR_DATA, PERF_TEST_DATA])
226 def 'Delete data nodes for multiple anchors'() {
227 given: 'a node with a large number of descendants is created'
228 createLineage(objectUnderTest, 50, 50, false)
229 createLineage(objectUnderTest, 50, 50, true)
230 when: 'data nodes are deleted'
232 objectUnderTest.deleteDataNodes(PERF_DATASPACE, [PERF_ANCHOR])
234 def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
235 then: 'delete duration is under 300 milliseconds'
236 recordAndAssertPerformance('Delete data nodes for anchors', 300, deleteDurationInMillis)