1bda3c24235d8d0d001f9e2cb72bae772351a52d
[cps.git] /
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.policyexecutor.stub.controller
22
23 import com.fasterxml.jackson.databind.ObjectMapper
24 import org.onap.cps.policyexecutor.stub.model.Operation
25 import org.onap.cps.policyexecutor.stub.model.PermissionRequest
26 import org.onap.cps.policyexecutor.stub.model.PermissionResponse
27 import org.spockframework.spring.SpringBean
28 import org.springframework.beans.factory.annotation.Autowired
29 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
30 import org.springframework.http.HttpStatus
31 import org.springframework.http.MediaType
32 import org.springframework.test.web.servlet.MockMvc
33 import spock.lang.Specification
34
35 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
36
37 @WebMvcTest(PolicyExecutorStubController)
38 class PolicyExecutorStubControllerSpec extends Specification {
39
40     @Autowired
41     MockMvc mockMvc
42
43     @Autowired
44     ObjectMapper objectMapper
45
46     @SpringBean
47     Sleeper sleeper = Spy()
48
49     def url = '/operation-permission/v1/permissions'
50
51     def 'Permission request with #resourceIdentifier.'() {
52         given: 'a permission request with target: #targetIdentifier'
53             def requestBody = createRequestBody(resourceIdentifier)
54         when: 'request is posted'
55             def response = mockMvc.perform(post(url)
56                     .header('Authorization','some string')
57                     .contentType(MediaType.APPLICATION_JSON)
58                     .content(requestBody))
59                     .andReturn().response
60         then: 'response status is Ok'
61             assert response.status == HttpStatus.OK.value()
62         and: 'the response body has the expected decision details'
63             def responseBody = response.contentAsString
64             def permissionResponse = objectMapper.readValue(responseBody, PermissionResponse.class)
65             assert permissionResponse.id == expectedId
66             assert permissionResponse.permissionResult == expectedResult
67             assert permissionResponse.message == expectedMessage
68         where: 'the following targets are used'
69             resourceIdentifier                             || expectedId | expectedResult | expectedMessage
70             'some fdn'                                     || '1'        | 'allow'        | 'all good'
71             'prefix/policySimulation=slowResponse_1'       || '2'        | 'allow'        | 'all good'
72             'prefix/policySimulation=policyResponse_deny'  || '3'        | 'deny'         | 'Stub is mocking a policy response: deny'
73             'prefix/policySimulation=policyResponse_other' || '4'        | 'other'        | 'Stub is mocking a policy response: other'
74
75     }
76
77     def 'Permission request with a HTTP error code.'() {
78         given: 'a permission request with a target fdn to simulate an http error code'
79             def requestBody = createRequestBody('segment1=1/policySimulation=httpError_418')
80         when: 'request is posted'
81             def response = mockMvc.perform(post(url)
82                 .header('Authorization','some string')
83                 .contentType(MediaType.APPLICATION_JSON)
84                 .content(requestBody))
85                 .andReturn().response
86         then: 'response status the same error code as in target fdn'
87             assert response.status == 418
88     }
89
90     def 'Permission request without authorization header.'() {
91         given: 'a valid permission request'
92             def requestBody = createRequestBody('some target')
93         when: 'request is posted without authorization header'
94             def response = mockMvc.perform(post(url)
95                 .contentType(MediaType.APPLICATION_JSON)
96                 .content(requestBody))
97                 .andReturn().response
98         then: 'response status is OK'
99             assert response.status == HttpStatus.OK.value()
100     }
101
102     def 'Permission request with no operations.'() {
103         given: 'a permission request with no operations'
104             def permissionRequest = new PermissionRequest('some decision type', [])
105             def requestBody = objectMapper.writeValueAsString(permissionRequest)
106         when: 'request is posted'
107             def response = mockMvc.perform(post(url)
108                 .header('Authorization','some string')
109                 .contentType(MediaType.APPLICATION_JSON)
110                 .content(requestBody))
111                 .andReturn().response
112         then: 'response status is Bad Request'
113             assert response.status == HttpStatus.BAD_REQUEST.value()
114     }
115
116     def 'Request with invalid json for request data.'() {
117         when: 'request with invalid json is posted'
118             def response = mockMvc.perform(post(url)
119                 .header('Authorization','some string')
120                 .contentType(MediaType.APPLICATION_JSON)
121                 .content('invalid json'))
122                 .andReturn().response
123         then: 'response status is Bad Request'
124             assert response.status == HttpStatus.BAD_REQUEST.value()
125     }
126
127     def 'Permission request with interrupted exception during slow response.'() {
128         given: 'a permission request with a target fdn to simulate a slow response'
129             def requestBody = createRequestBody('policySimulation=slowResponse_5')
130             sleeper.haveALittleRest(_) >> { throw new InterruptedException() }
131         when: 'request is posted'
132             mockMvc.perform(post(url)
133                 .header('Authorization','some string')
134                 .contentType(MediaType.APPLICATION_JSON)
135                 .content(requestBody))
136         then: 'response status is Bad Request'
137             noExceptionThrown()
138     }
139
140     def 'Permission request with missing or invalid attributes.'() {
141         given: 'Permission request with operation=#operation and resourceIdentifier=#resourceIdentifier'
142             def requestBody = createRequestBody(operation, 'some resource', changeRequest)
143         when: 'request is posted'
144             def response = mockMvc.perform(post(url)
145                 .header('Authorization','something')
146                 .contentType(MediaType.APPLICATION_JSON)
147                 .content(requestBody))
148                 .andReturn().response
149         then: 'response status as expected'
150             assert response.status == expectedStatus.value()
151         where: 'following parameters are used'
152             operation | changeRequest || expectedStatus
153             'delete'  | null          || HttpStatus.OK
154             'other'   | '{}'          || HttpStatus.OK
155             'other'   | null          || HttpStatus.BAD_REQUEST
156     }
157
158     def createRequestBody(resourceIdentifier) {
159         return createRequestBody('delete', resourceIdentifier, '{}')
160     }
161
162     def createRequestBody(operationName, resourceIdentifier, changeRequest) {
163         def operation = new Operation(operationName, 'some cm-handle')
164         operation.setChangeRequest(changeRequest)
165         operation.setResourceIdentifier(resourceIdentifier)
166         def permissionRequest = new PermissionRequest('cm-legacy', [operation])
167         return objectMapper.writeValueAsString(permissionRequest)
168     }
169
170 }