c8e34b1a5e0b05f42b5795e27d06f9eda5d686dc
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / impl / client / DmiRestClientSpec.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2021-2023 Nordix Foundation
4  *  Modifications Copyright (C) 2022 Bell Canada
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 package org.onap.cps.ncmp.api.impl.client
23
24 import com.fasterxml.jackson.databind.JsonNode
25 import com.fasterxml.jackson.databind.ObjectMapper
26 import com.fasterxml.jackson.databind.node.ObjectNode
27 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
28 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
29 import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
30 import org.onap.cps.ncmp.utils.TestUtils
31 import org.spockframework.spring.SpringBean
32 import org.springframework.beans.factory.annotation.Autowired
33 import org.springframework.boot.test.context.SpringBootTest
34 import org.springframework.http.HttpEntity
35 import org.springframework.http.HttpHeaders
36 import org.springframework.http.HttpStatus
37 import org.springframework.http.ResponseEntity
38 import org.springframework.test.context.ContextConfiguration
39 import org.springframework.web.client.HttpServerErrorException
40 import org.springframework.web.client.RestTemplate
41 import spock.lang.Specification
42
43 import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
44 import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
45 import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
46
47 @SpringBootTest
48 @ContextConfiguration(classes = [DmiProperties, DmiRestClient, ObjectMapper])
49 class DmiRestClientSpec extends Specification {
50
51     static final NO_AUTH_HEADER = null
52     static final BASIC_AUTH_HEADER = 'Basic c29tZS11c2VyOnNvbWUtcGFzc3dvcmQ='
53     static final BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
54
55     @SpringBean
56     RestTemplate mockRestTemplate = Mock(RestTemplate)
57
58     @Autowired
59     NcmpConfiguration.DmiProperties dmiProperties
60
61     @Autowired
62     DmiRestClient objectUnderTest
63
64     @Autowired
65     ObjectMapper objectMapper
66
67     def responseFromRestTemplate = Mock(ResponseEntity)
68
69     def 'DMI POST operation with JSON.'() {
70         given: 'the rest template returns a valid response entity for the expected parameters'
71             mockRestTemplate.postForEntity('my url', _ as HttpEntity, Object.class) >> responseFromRestTemplate
72         when: 'POST operation is invoked'
73             def result = objectUnderTest.postOperationWithJsonData('my url', 'some json', READ, null)
74         then: 'the output of the method is equal to the output from the test template'
75             result == responseFromRestTemplate
76     }
77
78     def 'Failing DMI POST operation.'() {
79         given: 'the rest template returns a valid response entity'
80             def serverResponse = 'server response'.getBytes()
81             def httpServerErrorException = new HttpServerErrorException(HttpStatus.FORBIDDEN, 'status text', serverResponse, null)
82             mockRestTemplate.postForEntity(*_) >> { throw httpServerErrorException }
83         when: 'POST operation is invoked'
84             def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation, null)
85         then: 'a Http Client Exception is thrown'
86             def thrown = thrown(HttpClientRequestException)
87         and: 'the exception has the relevant details from the error response'
88             assert thrown.httpStatus == 403
89             assert thrown.message == "Unable to ${operation} resource data."
90             assert thrown.details == 'server response'
91         where: 'the following operation is executed'
92             operation << [CREATE, READ, PATCH]
93     }
94
95     def 'Dmi trust level is determined by spring boot health status'() {
96         given: 'a health check response'
97             def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
98             def jsonNode = objectMapper.readValue(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
99             ((ObjectNode) jsonNode).put('status', 'my status')
100             mockRestTemplate.getForObject(*_) >> {jsonNode}
101         when: 'get trust level of the dmi plugin'
102             def result = objectUnderTest.getDmiHealthStatus('some url')
103         then: 'the status value from the json is return'
104             assert result == 'my status'
105     }
106
107     def 'Failing to get dmi plugin health status #scenario'() {
108         given: 'rest template with #scenario'
109             mockRestTemplate.getForObject(*_) >> healthStatusResponse
110         when: 'attempt to get health status of the dmi plugin'
111             def result = objectUnderTest.getDmiHealthStatus('some url')
112         then: 'result will be empty'
113             assert result == ''
114         where: 'the following responses are used'
115             scenario    | healthStatusResponse
116             'null'      | null
117             'exception' | {throw new Exception()}
118     }
119
120     def 'DMI auth header #scenario'() {
121         when: 'Specific dmi properties are provided'
122             dmiProperties.dmiBasicAuthEnabled = authEnabled
123         then: 'http headers to conditionally have Authorization header'
124             def authHeaderValues = objectUnderTest.configureHttpHeaders(new HttpHeaders(), ncmpAuthHeader).getOrEmpty('Authorization')
125             def outputAuthHeader = (authHeaderValues == null ? null : authHeaderValues[0])
126             assert outputAuthHeader == expectedAuthHeader
127         where: 'the following configurations are used'
128             scenario                                          | authEnabled | ncmpAuthHeader     || expectedAuthHeader
129             'DMI basic auth enabled, no NCMP bearer token'    | true        | NO_AUTH_HEADER     || BASIC_AUTH_HEADER
130             'DMI basic auth enabled, with NCMP bearer token'  | true        | BEARER_AUTH_HEADER || BASIC_AUTH_HEADER
131             'DMI basic auth disabled, no NCMP bearer token'   | false       | NO_AUTH_HEADER     || NO_AUTH_HEADER
132             'DMI basic auth disabled, with NCMP bearer token' | false       | BEARER_AUTH_HEADER || BEARER_AUTH_HEADER
133             'DMI basic auth disabled, with NCMP basic auth'   | false       | BASIC_AUTH_HEADER  || NO_AUTH_HEADER
134     }
135
136 }