From 4c9af4a90ce9899bdc84695cb7f038d2f4ab0f1b Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Tue, 19 Aug 2025 17:09:48 +0530 Subject: [PATCH] Performance tests for CPS Delta APIs - Performance tests for two Delta APIs - Delta Between 2 anchors - Delta between an anchor and JSON payload - Tests are inclusive of old and new delta report formats. - Added a method to generate anchors with modified openroadm data - Added a method to reset test data for an anchor Issue-ID: CPS-2839 Change-Id: I8ec3a265c5fa02b8cd9060b65fee79a6ca9366e0 Signed-off-by: Arpit Singh --- .../performance/base/CpsPerfTestBase.groovy | 80 ++++++++++++-- .../performance/cps/DeltaPerfTest.groovy | 115 +++++++++++++++++++++ 2 files changed, 187 insertions(+), 8 deletions(-) create mode 100644 integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/DeltaPerfTest.groovy diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/CpsPerfTestBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/CpsPerfTestBase.groovy index f2d3efd385..0a1badfe45 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/CpsPerfTestBase.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/CpsPerfTestBase.groovy @@ -21,12 +21,16 @@ package org.onap.cps.integration.performance.base +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import org.onap.cps.api.parameters.FetchDescendantsOption import org.onap.cps.integration.ResourceMeter import org.onap.cps.rest.utils.MultipartFileUtil -import org.onap.cps.api.parameters.FetchDescendantsOption import org.onap.cps.utils.ContentType import org.springframework.web.multipart.MultipartFile +import java.time.OffsetDateTime + class CpsPerfTestBase extends PerfTestBase { static final def CPS_PERFORMANCE_TEST_DATASPACE = 'cpsPerformanceDataspace' @@ -52,6 +56,16 @@ class CpsPerfTestBase extends PerfTestBase { def createInitialData() { addOpenRoadModel() addOpenRoadData() + addModifiedOpenRoadData() + } + + def 'CPS pre-load test data'() { + when: 'dummy get data nodes runs so that populating the DB does not get included in other test timings' + resourceMeter.start() + def result = cpsDataService.getDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', '/', FetchDescendantsOption.OMIT_DESCENDANTS) + resourceMeter.stop() + then: 'expected data exists' + assert result.xpath == ['/openroadm-devices'] } def addOpenRoadModel() { @@ -78,13 +92,63 @@ class CpsPerfTestBase extends PerfTestBase { ']}}' } - def 'CPS pre-load test data'() { - when: 'dummy get data nodes runs so that populating the DB does not get included in other test timings' - resourceMeter.start() - def result = cpsDataService.getDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', '/', FetchDescendantsOption.OMIT_DESCENDANTS) - resourceMeter.stop() - then: 'expected data exists' - assert result.xpath == ['/openroadm-devices'] + def addModifiedOpenRoadData() { + def data = generateModifiedOpenRoadData(OPENROADM_DEVICES_PER_ANCHOR, 200, 200, 200) + resourceMeter.start() + addAnchorsWithData(1, CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, 'openroadm-modified', data, ContentType.JSON) + resourceMeter.stop() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + recordAndAssertResourceUsage('CPS:Creating modified openroadm anchor with large data tree', 100, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB(), false) + } + + def generateModifiedOpenRoadData(numberOfNodes, removeNodesCount, addNodesCount, updateCount) { + def innerNode = readResourceDataFile('openroadm/innerNode.json') + def allIndices = (0.. + def jsonNode = slurper.parseText(data) + if (idx < updateCount) { + jsonNode['status'] = 'fail' + def childNode = jsonNode['org-openroadm-device']['degree'][0] + if (childNode) { + childNode['max-wavelengths'] += 100 + } + } + return JsonOutput.toJson(jsonNode) + } + } + + def resetTestAnchorData() { + cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1') + def data = generateOpenRoadData(OPENROADM_DEVICES_PER_ANCHOR) + cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, 'openroadm1') + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', data, OffsetDateTime.now()) } } diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/DeltaPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/DeltaPerfTest.groovy new file mode 100644 index 0000000000..02eecb644d --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/DeltaPerfTest.groovy @@ -0,0 +1,115 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 TechMahindra Ltd. + * ================================================================================ + * 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.integration.performance.cps + + +import org.onap.cps.api.CpsDeltaService +import org.onap.cps.integration.performance.base.CpsPerfTestBase + +import static org.onap.cps.api.parameters.FetchDescendantsOption.DIRECT_CHILDREN_ONLY +import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS + +class DeltaPerfTest extends CpsPerfTestBase{ + CpsDeltaService objectUnderTest + def setup() { + objectUnderTest = cpsDeltaService + } + + def jsonPayload = generateModifiedOpenRoadData(1000, 200, 200, 200) + + def 'Get delta between 2 anchors wtih grouping enabled and #scenario'() { + when: 'attempt to get delta between two 2 anchors' + resourceMeter.start() + 10.times { + objectUnderTest.getDeltaByDataspaceAndAnchors(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', 'openroadm-modified1', xpath, fetchDescendantsOption, true) + } + resourceMeter.stop() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + then: 'the delta is returned and operation completes within expected time' + recordAndAssertResourceUsage('CPS:Get delta between 2 anchors', expectedDuration, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB()) + where: 'the following parameters are used' + scenario | xpath | fetchDescendantsOption || expectedDuration + 'no descendants' | '/openroadm-devices/openroadm-device[@device-id=\'C201-7-1A-1\']' | OMIT_DESCENDANTS || 0.5 + 'direct descendants' | '/' | DIRECT_CHILDREN_ONLY || 1.5 + 'all descendants' | '/' | INCLUDE_ALL_DESCENDANTS || 15.0 + } + + def 'Get delta between 2 anchors with grouping disabled and #scenario'() { + when: 'attempt to get delta between two 2 anchors with grouping disabled' + resourceMeter.start() + 10.times { + objectUnderTest.getDeltaByDataspaceAndAnchors(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', 'openroadm-modified1', xpath, fetchDescendantsOption, false) + } + resourceMeter.stop() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + then: 'the delta is returned and operation completes within expected time' + recordAndAssertResourceUsage('CPS:Get delta between 2 anchors with grouping disabled', expectedDuration, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB()) + where: 'the following parameters are used' + scenario | xpath | fetchDescendantsOption || expectedDuration + 'no descendants' | '/openroadm-devices/openroadm-device[@device-id=\'C201-7-1A-1\']' | OMIT_DESCENDANTS || 0.3 + 'direct descendants' | '/openroadm-devices' | DIRECT_CHILDREN_ONLY || 0.5 + 'all descendants' | '/openroadm-devices' | INCLUDE_ALL_DESCENDANTS || 12.0 + } + + def 'Get delta between an anchor and JSON payload with grouping enabled and #scenario'() { + when: 'attempt to get delta between an anchor and JSON payload with grouping enabled' + resourceMeter.start() + objectUnderTest.getDeltaByDataspaceAnchorAndPayload(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', '/openroadm-devices', Collections.emptyMap(), jsonPayload, fetchDescendantsOption, true) + resourceMeter.stop() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + then: 'the delta is returned and operation completes within expected time' + recordAndAssertResourceUsage('CPS:Get delta between an anchor and JSON payload with grouping enabled', expectedDuration, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB()) + where: 'the following parameters are used' + scenario | fetchDescendantsOption || expectedDuration + 'no descendants' | OMIT_DESCENDANTS || 2.0 + 'direct descendants' | DIRECT_CHILDREN_ONLY || 2.0 + 'all descendants' | INCLUDE_ALL_DESCENDANTS || 3.5 + } + + def 'Get delta between an anchor and JSON payload with grouping disabled'() { + when: 'attempt to get delta between an anchor and JSON payload with grouping disabled' + resourceMeter.start() + objectUnderTest.getDeltaByDataspaceAnchorAndPayload(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', '/openroadm-devices', Collections.emptyMap(), jsonPayload, INCLUDE_ALL_DESCENDANTS, false) + resourceMeter.stop() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + then: 'the delta is returned and operation completes within expected time' + recordAndAssertResourceUsage('CPS:Get delta between an anchor and JSON payload with grouping disabled', expectedDuration, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB()) + where: 'the following parameters are used' + scenario | fetchDescendantsOption || expectedDuration + 'no descendants' | OMIT_DESCENDANTS || 3.0 + 'direct descendants' | DIRECT_CHILDREN_ONLY || 3.0 + 'all descendants' | INCLUDE_ALL_DESCENDANTS || 3.5 + } + + def 'Apply delta report to an anchor'() { + given: 'a delta report between 2 anchors' + def deltaReport = objectUnderTest.getDeltaByDataspaceAndAnchors(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', 'openroadm-modified1', '/openroadm-devices', INCLUDE_ALL_DESCENDANTS, true) + def deltaReportAsJson = jsonObjectMapper.asJsonString(deltaReport) + when: 'attempt to apply the delta report to an anchor' + resourceMeter.start() + objectUnderTest.applyChangesInDeltaReport(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', deltaReportAsJson) + resourceMeter.stop() + resetTestAnchorData() + def durationInSeconds = resourceMeter.getTotalTimeInSeconds() + then: 'the delta is applied and operation completes within expected time' + recordAndAssertResourceUsage('CPS:Apply delta report to an anchor', 8.0, durationInSeconds, resourceMeter.getTotalMemoryUsageInMB()) + } +} -- 2.16.6