f9a98949905c83c3ee0047d59bcbcbc2c7f9554e
[cps.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024-2026 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
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.ncmp.impl.data.policyexecutor
22
23 import com.fasterxml.jackson.databind.ObjectMapper
24 import org.onap.cps.ncmp.api.exceptions.ProvMnSException
25 import org.onap.cps.ncmp.impl.provmns.RequestParameters
26 import org.onap.cps.ncmp.impl.provmns.model.PatchItem
27 import org.onap.cps.ncmp.impl.provmns.model.ResourceOneOf
28 import org.onap.cps.utils.JsonObjectMapper
29 import spock.lang.Specification
30
31 import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE
32 import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE
33 import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE
34
35 class OperationDetailsFactorySpec extends Specification {
36
37     def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
38     def requestPathParameters = new RequestParameters('some method', '/parent=id1/someChild=someId','some uri', 'class from uri', 'id from uri')
39
40     OperationDetailsFactory objectUnderTest = new OperationDetailsFactory(jsonObjectMapper)
41
42     def 'Build replace (~create) operation details with all properties where class name in body is #scenario.'() {
43         given: 'a resource'
44             def resource = new ResourceOneOf(id: 'some resource id', objectClass: classNameInBody)
45         when: 'replace operation details are built'
46             def result = objectUnderTest.buildOperationDetails(CREATE, requestPathParameters, resource)
47         then: 'all details are correct'
48             assert result.parentFdn == '/parent=id1'
49             assert result.className == 'class from uri'
50             assert result.ClassInstances[0].id == 'id from uri'
51         where:
52             scenario    | classNameInBody
53             'populated' | 'class in body'
54             'empty'     | ''
55             'null'      | null
56     }
57
58     def 'Single patch operation with #patchOperationType checks correct operation type.'() {
59         given: 'a resource and single patch item'
60             def resource = new ResourceOneOf(id: 'some resource id')
61             def patchItem = new PatchItem(op: patchOperationType, 'path':'some uri', value: resource)
62         when: 'operation details is created'
63             def result = objectUnderTest.buildOperationDetails(requestPathParameters, patchItem)
64         then: 'it has the correct operation type (for Policy Executor check)'
65             assert result.operationType == expectedPolicyExecutorOperationType
66         where: 'following operations are used'
67             patchOperationType | expectedPolicyExecutorOperationType
68             'ADD'              | CREATE
69             'REPLACE'          | UPDATE
70             'REMOVE'           | DELETE
71     }
72
73     def 'Build policy executor patch operation details with single replace operation and #scenario.'() {
74         given: 'a patchItem'
75             def patchItem = new PatchItem(op: 'REPLACE', 'path':"some uri${suffix}", value: value)
76         when: 'patch operation details are checked'
77             def result = objectUnderTest.buildOperationDetails(requestPathParameters, patchItem)
78         then: 'Attribute value is correct'
79             result.ClassInstances[0].attributes == [attr1:456]
80         where: 'attributes are set using # or resource'
81             scenario                            | suffix               | value
82             'set simple value using #'          | '#/attributes/attr1' | 456
83             'set complex value using resource'  | ''                   | [id:'id1', attributes:[attr1:456]]
84     }
85
86     def 'Build an attribute map with different depths of hierarchy with #scenario.'() {
87         given: 'a patch item with a path'
88             def patchItem = new PatchItem(op: 'REPLACE', 'path':path, value: 123)
89         when: 'transforming the attributes'
90             def hierarchyMap = objectUnderTest.createNestedMap(patchItem)
91         then: 'the map depth is equal to the expected number of attributes'
92             assert hierarchyMap.get(expectedAttributeName).toString() == expectedAttributeValue
93         where: 'simple and complex attributes are tested'
94             scenario                                   | path                                                             || expectedAttributeName || expectedAttributeValue
95             'set a simple attribute'                   | 'myUriLdnFirstPart#/attributes/simpleAttribute'                  || 'simpleAttribute'     || '123'
96             'set a simple attribute with a trailing /' | 'myUriLdnFirstPart#/attributes/simpleAttribute/'                 || 'simpleAttribute'     || '123'
97             'set a complex attribute'                  | 'myUriLdnFirstPart#/attributes/complexAttribute/simpleAttribute' || 'complexAttribute'    || '[simpleAttribute:123]'
98     }
99
100     def 'Attempt to Build Operation details with unsupported op (MOVE).'() {
101         given: 'a patchItem'
102             def patchItem = new PatchItem(op: 'MOVE', 'path':'some uri')
103         when: 'a build is attempted with an unsupported op'
104             objectUnderTest.buildOperationDetails(requestPathParameters, patchItem)
105         then: 'the result is as expected (exception thrown)'
106             def exceptionThrown = thrown(ProvMnSException)
107             assert exceptionThrown.title == 'Unsupported Patch Operation Type: move'
108     }
109
110 }