summaryrefslogtreecommitdiffstats
path: root/cps-ri
diff options
context:
space:
mode:
authordanielhanrahan <daniel.hanrahan@est.tech>2023-01-12 09:55:56 +0000
committerdanielhanrahan <daniel.hanrahan@est.tech>2023-01-17 12:59:51 +0000
commit35e5646fef7402cb922cb20ef08cfd4e032a4a2c (patch)
tree09d4920c8403ae4cf4cc0aa1aabdcf113107ec5c /cps-ri
parentecfce9d3e46410e1158c0f640fa833c101c4bda4 (diff)
Add delete performance tests
- move existing delete tests to new class - add tests for deleting lists and list elements - add test for deleting root node Issue-ID: CPS-1437 Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech> Change-Id: I81228aa9473ed28d550db64b28c38abb1c1016f5
Diffstat (limited to 'cps-ri')
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistencePerfSpecBase.groovy74
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy154
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy86
3 files changed, 236 insertions, 78 deletions
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistencePerfSpecBase.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistencePerfSpecBase.groovy
new file mode 100644
index 000000000..3bbae2d08
--- /dev/null
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistencePerfSpecBase.groovy
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.spi.impl
+
+import org.onap.cps.spi.model.DataNode
+import org.onap.cps.spi.model.DataNodeBuilder
+
+class CpsPersistencePerfSpecBase extends CpsPersistenceSpecBase {
+
+ static final String PERF_TEST_DATA = '/data/perf-test.sql'
+ static final String PERF_DATASPACE = 'PERF-DATASPACE'
+ static final String PERF_ANCHOR = 'PERF-ANCHOR'
+ static final String PERF_TEST_PARENT = '/perf-parent-1'
+
+ static def xpathsToAllGrandChildren = []
+
+ def createLineage(cpsDataPersistenceService, numberOfChildren, numberOfGrandChildren, createLists) {
+ xpathsToAllGrandChildren = []
+ (1..numberOfChildren).each {
+ if (createLists) {
+ def xpathFormat = "${PERF_TEST_PARENT}/perf-test-list-${it}[@key='%d']"
+ def listElements = goForthAndMultiply(xpathFormat, numberOfGrandChildren)
+ cpsDataPersistenceService.addListElements(PERF_DATASPACE, PERF_ANCHOR, PERF_TEST_PARENT, listElements)
+ } else {
+ def xpathFormat = "${PERF_TEST_PARENT}/perf-test-child-${it}/perf-test-grand-child-%d"
+ def grandChildren = goForthAndMultiply(xpathFormat, numberOfGrandChildren)
+ def child = new DataNodeBuilder()
+ .withXpath("${PERF_TEST_PARENT}/perf-test-child-${it}")
+ .withChildDataNodes(grandChildren)
+ .build()
+ cpsDataPersistenceService.addChildDataNode(PERF_DATASPACE, PERF_ANCHOR, PERF_TEST_PARENT, child)
+ }
+ }
+ }
+
+ def goForthAndMultiply(xpathFormat, numberOfGrandChildren) {
+ def grandChildren = []
+ (1..numberOfGrandChildren).each {
+ def xpath = String.format(xpathFormat as String, it)
+ def grandChild = new DataNodeBuilder().withXpath(xpath).build()
+ xpathsToAllGrandChildren.add(grandChild.xpath)
+ grandChildren.add(grandChild)
+ }
+ return grandChildren
+ }
+
+ def countDataNodes(dataNodes) {
+ int nodeCount = 1
+ for (DataNode parent : dataNodes) {
+ for (DataNode child : parent.childDataNodes) {
+ nodeCount = nodeCount + (countDataNodes(child))
+ }
+ }
+ return nodeCount
+ }
+}
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
new file mode 100644
index 000000000..5aae285d7
--- /dev/null
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
@@ -0,0 +1,154 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.spi.performance
+
+import org.onap.cps.spi.CpsDataPersistenceService
+import org.onap.cps.spi.impl.CpsPersistencePerfSpecBase
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.jdbc.Sql
+import org.springframework.util.StopWatch
+
+import java.util.concurrent.TimeUnit
+
+class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase {
+
+ @Autowired
+ CpsDataPersistenceService objectUnderTest
+
+ static def NUMBER_OF_CHILDREN = 100
+ static def NUMBER_OF_GRAND_CHILDREN = 50
+ static def NUMBER_OF_LISTS = 100
+ static def NUMBER_OF_LIST_ELEMENTS = 50
+ static def ALLOWED_SETUP_TIME_MS = TimeUnit.SECONDS.toMillis(10)
+
+ def stopWatch = new StopWatch()
+
+ @Sql([CLEAR_DATA, PERF_TEST_DATA])
+ def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
+ given: 'a node with a large number of descendants is created'
+ stopWatch.start()
+ createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
+ stopWatch.stop()
+ def setupDurationInMillis = stopWatch.getTotalTimeMillis()
+ and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
+ assert setupDurationInMillis < ALLOWED_SETUP_TIME_MS
+ }
+
+ def 'Delete 5 children with grandchildren'() {
+ when: 'child nodes are deleted'
+ stopWatch.start()
+ (1..5).each {
+ def childPath = "${PERF_TEST_PARENT}/perf-test-child-${it}".toString();
+ objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
+ }
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 6000 milliseconds'
+ assert deleteDurationInMillis < 6000
+ }
+
+ def 'Delete 50 grandchildren (that have no descendants)'() {
+ when: 'target nodes are deleted'
+ stopWatch.start()
+ (1..50).each {
+ def grandchildPath = "${PERF_TEST_PARENT}/perf-test-child-6/perf-test-grand-child-${it}".toString();
+ objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
+ }
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 500 milliseconds'
+ assert deleteDurationInMillis < 500
+ }
+
+ def 'Delete 1 large data node with many descendants'() {
+ when: 'parent node is deleted'
+ stopWatch.start()
+ objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, PERF_TEST_PARENT)
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 2500 milliseconds'
+ assert deleteDurationInMillis < 2500
+ }
+
+ @Sql([CLEAR_DATA, PERF_TEST_DATA])
+ def 'Create a node with many list elements (please note, subsequent tests depend on this running first).'() {
+ given: 'a node with a large number of descendants is created'
+ stopWatch.start()
+ createLineage(objectUnderTest, NUMBER_OF_LISTS, NUMBER_OF_LIST_ELEMENTS, true)
+ stopWatch.stop()
+ def setupDurationInMillis = stopWatch.getTotalTimeMillis()
+ and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
+ assert setupDurationInMillis < ALLOWED_SETUP_TIME_MS
+ }
+
+ def 'Delete 5 whole lists with many elements'() {
+ when: 'list nodes are deleted'
+ stopWatch.start()
+ (1..5).each {
+ def childPath = "${PERF_TEST_PARENT}/perf-test-list-${it}".toString();
+ objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, childPath)
+ }
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 4000 milliseconds'
+ assert deleteDurationInMillis < 4000
+ }
+
+ def 'Delete 10 list elements with keys'() {
+ when: 'list elements are deleted'
+ stopWatch.start()
+ (1..10).each {
+ def key = it.toString()
+ def grandchildPath = "${PERF_TEST_PARENT}/perf-test-list-6[@key='${key}']"
+ objectUnderTest.deleteListDataNode(PERF_DATASPACE, PERF_ANCHOR, grandchildPath)
+ }
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 6000 milliseconds'
+ assert deleteDurationInMillis < 6000
+ }
+
+ @Sql([CLEAR_DATA, PERF_TEST_DATA])
+ def 'Delete root node with many descendants'() {
+ given: 'a node with a large number of descendants is created'
+ createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
+ when: 'root node is deleted'
+ stopWatch.start()
+ objectUnderTest.deleteDataNode(PERF_DATASPACE, PERF_ANCHOR, '/')
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 250 milliseconds'
+ assert deleteDurationInMillis < 250
+ }
+
+ @Sql([CLEAR_DATA, PERF_TEST_DATA])
+ def 'Delete data nodes for an anchor'() {
+ given: 'a node with a large number of descendants is created'
+ createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
+ when: 'data nodes are deleted'
+ stopWatch.start()
+ objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR)
+ stopWatch.stop()
+ def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
+ then: 'delete duration is under 250 milliseconds'
+ assert deleteDurationInMillis < 250
+ }
+}
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy
index 45cdb4d07..28363d74b 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,11 +20,9 @@
package org.onap.cps.spi.performance
+import org.onap.cps.spi.impl.CpsPersistencePerfSpecBase
import org.springframework.util.StopWatch
import org.onap.cps.spi.CpsDataPersistenceService
-import org.onap.cps.spi.impl.CpsPersistenceSpecBase
-import org.onap.cps.spi.model.DataNode
-import org.onap.cps.spi.model.DataNodeBuilder
import org.onap.cps.spi.repository.AnchorRepository
import org.onap.cps.spi.repository.DataspaceRepository
import org.onap.cps.spi.repository.FragmentRepository
@@ -36,9 +34,7 @@ import java.util.concurrent.TimeUnit
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
-class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
-
- static final String PERF_TEST_DATA = '/data/perf-test.sql'
+class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
@Autowired
CpsDataPersistenceService objectUnderTest
@@ -52,7 +48,6 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
@Autowired
FragmentRepository fragmentRepository
- static def PERF_TEST_PARENT = '/perf-parent-1'
static def NUMBER_OF_CHILDREN = 200
static def NUMBER_OF_GRAND_CHILDREN = 50
static def TOTAL_NUMBER_OF_NODES = 1 + NUMBER_OF_CHILDREN + (NUMBER_OF_CHILDREN * NUMBER_OF_GRAND_CHILDREN) // Parent + Children + Grand-children
@@ -61,13 +56,12 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
def stopWatch = new StopWatch()
def readStopWatch = new StopWatch()
- static def xpathsToAllGrandChildren = []
@Sql([CLEAR_DATA, PERF_TEST_DATA])
def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
given: 'a node with a large number of descendants is created'
stopWatch.start()
- createLineage()
+ createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
stopWatch.stop()
def setupDurationInMillis = stopWatch.getTotalTimeMillis()
and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
@@ -77,7 +71,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
def 'Get data node with many descendants by xpath #scenario'() {
when: 'get parent is executed with all descendants'
stopWatch.start()
- def result = objectUnderTest.getDataNode('PERF-DATASPACE', 'PERF-ANCHOR', xpath, INCLUDE_ALL_DESCENDANTS)
+ def result = objectUnderTest.getDataNode(PERF_DATASPACE, PERF_ANCHOR, xpath, INCLUDE_ALL_DESCENDANTS)
stopWatch.stop()
def readDurationInMillis = stopWatch.getTotalTimeMillis()
then: 'read duration is under 500 milliseconds'
@@ -93,7 +87,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
def 'Query parent data node with many descendants by cps-path'() {
when: 'query is executed with all descendants'
stopWatch.start()
- def result = objectUnderTest.queryDataNodes('PERF-DATASPACE', 'PERF-ANCHOR', '//perf-parent-1' , INCLUDE_ALL_DESCENDANTS)
+ def result = objectUnderTest.queryDataNodes(PERF_DATASPACE, PERF_ANCHOR, '//perf-parent-1' , INCLUDE_ALL_DESCENDANTS)
stopWatch.stop()
def readDurationInMillis = stopWatch.getTotalTimeMillis()
then: 'read duration is under 500 milliseconds'
@@ -106,7 +100,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
when: 'we query for all grandchildren (except 1 for fun) with the new native method'
xpathsToAllGrandChildren.remove(0)
readStopWatch.start()
- def result = objectUnderTest.getDataNodes('PERF-DATASPACE', 'PERF-ANCHOR', xpathsToAllGrandChildren, INCLUDE_ALL_DESCENDANTS)
+ def result = objectUnderTest.getDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToAllGrandChildren, INCLUDE_ALL_DESCENDANTS)
readStopWatch.stop()
def readDurationInMillis = readStopWatch.getTotalTimeMillis()
then: 'the returned number of entities equal to the number of children * number of grandchildren'
@@ -118,7 +112,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
def 'Query many descendants by cps-path with #scenario'() {
when: 'query is executed with all descendants'
stopWatch.start()
- def result = objectUnderTest.queryDataNodes('PERF-DATASPACE', 'PERF-ANCHOR', '//perf-test-grand-child-1', descendantsOption)
+ def result = objectUnderTest.queryDataNodes(PERF_DATASPACE, PERF_ANCHOR, '//perf-test-grand-child-1', descendantsOption)
stopWatch.stop()
def readDurationInMillis = stopWatch.getTotalTimeMillis()
then: 'read duration is under 500 milliseconds'
@@ -130,68 +124,4 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistenceSpecBase {
'omit descendants ' | OMIT_DESCENDANTS || 150
'include descendants (although there are none)' | INCLUDE_ALL_DESCENDANTS || 150
}
-
- def 'Delete 50 grandchildren (that have no descendants)'() {
- when: 'target nodes are deleted'
- stopWatch.start()
- (1..NUMBER_OF_GRAND_CHILDREN).each {
- def grandchildPath = "${PERF_TEST_PARENT}/perf-test-child-1/perf-test-grand-child-${it}".toString();
- objectUnderTest.deleteDataNode('PERF-DATASPACE', 'PERF-ANCHOR', grandchildPath)
- }
- stopWatch.stop()
- def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
- then: 'delete duration is under 1000 milliseconds'
- assert deleteDurationInMillis < 1000
- }
-
- def 'Delete 5 children with grandchildren'() {
- when: 'child nodes are deleted'
- stopWatch.start()
- (1..5).each {
- def childPath = "${PERF_TEST_PARENT}/perf-test-child-${it}".toString();
- objectUnderTest.deleteDataNode('PERF-DATASPACE', 'PERF-ANCHOR', childPath)
- }
- stopWatch.stop()
- def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
- then: 'delete duration is under 10000 milliseconds'
- assert deleteDurationInMillis < 10000
- }
-
- def 'Delete 1 large data node with many descendants'() {
- when: 'parent node is deleted'
- stopWatch.start()
- objectUnderTest.deleteDataNode('PERF-DATASPACE', 'PERF-ANCHOR', PERF_TEST_PARENT)
- stopWatch.stop()
- def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
- then: 'delete duration is under 5000 milliseconds'
- assert deleteDurationInMillis < 5000
- }
-
- def createLineage() {
- (1..NUMBER_OF_CHILDREN).each {
- def childName = "perf-test-child-${it}".toString()
- def child = goForthAndMultiply(PERF_TEST_PARENT, childName)
- objectUnderTest.addChildDataNode('PERF-DATASPACE', 'PERF-ANCHOR', PERF_TEST_PARENT, child)
- }
- }
-
- def goForthAndMultiply(parentXpath, childName) {
- def grandChildren = []
- (1..NUMBER_OF_GRAND_CHILDREN).each {
- def grandChild = new DataNodeBuilder().withXpath("${parentXpath}/${childName}/perf-test-grand-child-${it}").build()
- xpathsToAllGrandChildren.add(grandChild.xpath)
- grandChildren.add(grandChild)
- }
- return new DataNodeBuilder().withXpath("${parentXpath}/${childName}").withChildDataNodes(grandChildren).build()
- }
-
- def countDataNodes(dataNodes) {
- int nodeCount = 1
- for (DataNode parent : dataNodes) {
- for (DataNode child : parent.childDataNodes) {
- nodeCount = nodeCount + (countDataNodes(child))
- }
- }
- return nodeCount
- }
}