2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
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.integration.performance.cps
23 import org.onap.cps.integration.performance.base.CpsPerfTestBase
24 import org.onap.cps.api.model.ModuleReference
26 class ModuleQueryPerfTest extends CpsPerfTestBase {
28 static final KILOBYTE = 1000
29 static final TOTAL_TEST_ANCHORS = 10_000
30 static final SCHEMA_SET_PREFIX = 'mySchemaSet'
31 static final ANCHOR_PREFIX = 'myAnchor'
32 static final MODULE_REVISION = '2024-04-25'
33 static final MODULE_TEMPLATE = """
34 module <MODULE_NAME> {
36 namespace "org:onap:cps:test:<MODULE_NAME>";
38 revision "<MODULE_REVISION>" {
39 description "<DESCRIPTION>";
52 def 'Module query - Preload test data (needed for other tests).'() {
53 given: 'a schema set with different sizes of Yang modules is created'
54 cpsModuleService.createSchemaSet(CPS_PERFORMANCE_TEST_DATASPACE, SCHEMA_SET_PREFIX + '0', [
55 'module0.yang': makeYangModuleOfLength('module0', 1 * KILOBYTE),
56 'module1.yang': makeYangModuleOfLength('module1', 1000 * KILOBYTE)
58 and: 'these modules will be used again to create many schema sets'
59 def allModuleReferences = [
60 new ModuleReference('module0', MODULE_REVISION),
61 new ModuleReference('module1', MODULE_REVISION)
63 when: 'many schema sets and anchors are created using those modules'
65 (1..TOTAL_TEST_ANCHORS).each {
66 def schemaSetName = SCHEMA_SET_PREFIX + it
67 def anchorName = ANCHOR_PREFIX + it
68 cpsModuleService.createSchemaSetFromModules(CPS_PERFORMANCE_TEST_DATASPACE, schemaSetName, [:], allModuleReferences)
69 cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, schemaSetName, anchorName)
72 then: 'operation takes less than expected duration'
73 recordAndAssertResourceUsage('Module query test setup', 90, resourceMeter.totalTimeInSeconds, 500, resourceMeter.totalMemoryUsageInMB
77 def 'Querying anchors by module name is NOT dependant on the file size of the module.'() {
78 when: 'we search for anchors with given Yang module name'
80 def result = cpsAnchorService.queryAnchorNames(CPS_PERFORMANCE_TEST_DATASPACE, [yangModuleName])
82 then: 'expected number of anchors is returned'
83 assert result.size() == TOTAL_TEST_ANCHORS
84 and: 'operation completes with expected resource usage'
85 recordAndAssertResourceUsage("Query for anchors with ${scenario}", 0.1, resourceMeter.totalTimeInSeconds, 5, resourceMeter.totalMemoryUsageInMB)
86 where: 'the following parameters are used'
87 scenario | yangModuleName
88 '1 KB module' | 'module0'
89 '1000 KB module' | 'module1'
92 def 'Module query - Clean up test data.'() {
94 // FIXME this API has extremely high memory usage, therefore external batching must be used
95 for (int i = 1; i <= TOTAL_TEST_ANCHORS; i += 100) {
96 cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, (i..i+100).collect {SCHEMA_SET_PREFIX + it})
98 cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, [SCHEMA_SET_PREFIX + '0'])
99 cpsModuleService.deleteAllUnusedYangModuleData(CPS_PERFORMANCE_TEST_DATASPACE)
102 // This makes a Yang module of approximately target length in bytes by padding the description field with many '*'
103 private static def makeYangModuleOfLength(moduleName, targetLength) {
104 def padding = String.valueOf('*').repeat(targetLength - MODULE_TEMPLATE.size()) // not exact
105 return MODULE_TEMPLATE
106 .replaceAll('<MODULE_NAME>', moduleName)
107 .replaceAll('<MODULE_REVISION>', MODULE_REVISION)
108 .replaceAll('<DESCRIPTION>', padding)