Merge "Schedule response to client"
[cps.git] / integration-test / src / test / groovy / org / onap / cps / integration / performance / cps / ModuleQueryPerfTest.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024 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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.integration.performance.cps
22
23 import org.onap.cps.integration.performance.base.CpsPerfTestBase
24 import org.onap.cps.spi.model.ModuleReference
25
26 class ModuleQueryPerfTest extends CpsPerfTestBase {
27
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> {
35             yang-version 1.1;
36             namespace "org:onap:cps:test:<MODULE_NAME>";
37             prefix tree;
38             revision "<MODULE_REVISION>" {
39                 description "<DESCRIPTION>";
40             }
41             container tree {
42                 list branch {
43                     key "name";
44                     leaf name {
45                         type string;
46                     }
47                 }
48             }
49         }
50     """
51
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)
57             ])
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)
62             ]
63         when: 'many schema sets and anchors are created using those modules'
64             resourceMeter.start()
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)
70             }
71             resourceMeter.stop()
72         then: 'operation takes less than expected duration'
73             recordAndAssertResourceUsage('Module query test setup',
74                     45, resourceMeter.totalTimeInSeconds,
75                     500, resourceMeter.totalMemoryUsageInMB
76             )
77     }
78
79     def 'Querying anchors by module name is NOT dependant on the file size of the module.'() {
80         when: 'we search for anchors with given Yang module name'
81             resourceMeter.start()
82             def result = cpsAnchorService.queryAnchorNames(CPS_PERFORMANCE_TEST_DATASPACE, [yangModuleName])
83             resourceMeter.stop()
84         then: 'expected number of anchors is returned'
85             assert result.size() == TOTAL_TEST_ANCHORS
86         and: 'operation completes with expected resource usage'
87             recordAndAssertResourceUsage("Query for anchors with ${scenario}",
88                     expectedTimeInSeconds, resourceMeter.totalTimeInSeconds,
89                     5, resourceMeter.totalMemoryUsageInMB)
90         where: 'the following parameters are used'
91             scenario         | yangModuleName || expectedTimeInSeconds
92             '1 KB module'    | 'module0'      || 0.05
93             '1000 KB module' | 'module1'      || 0.05
94     }
95
96     def 'Module query - Clean up test data.'() {
97         cleanup:
98             // FIXME this API has extremely high memory usage, therefore external batching must be used
99             for (int i = 1; i <= TOTAL_TEST_ANCHORS; i += 100) {
100                 cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, (i..i+100).collect {SCHEMA_SET_PREFIX + it})
101             }
102             cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, [SCHEMA_SET_PREFIX + '0'])
103     }
104
105     // This makes a Yang module of approximately target length in bytes by padding the description field with many '*'
106     private static def makeYangModuleOfLength(moduleName, targetLength) {
107         def padding = String.valueOf('*').repeat(targetLength - MODULE_TEMPLATE.size()) // not exact
108         return MODULE_TEMPLATE
109                 .replaceAll('<MODULE_NAME>', moduleName)
110                 .replaceAll('<MODULE_REVISION>', MODULE_REVISION)
111                 .replaceAll('<DESCRIPTION>', padding)
112     }
113 }