/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation
+ * Copyright (C) 2021-2023 Nordix Foundation
+ * Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.ncmp.api.impl.client
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.node.ObjectNode
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
+import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
+import org.onap.cps.ncmp.utils.TestUtils
+import org.spockframework.spring.SpringBean
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.web.client.HttpServerErrorException
import org.springframework.web.client.RestTemplate
import spock.lang.Specification
-import org.springframework.http.HttpMethod
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+
+@SpringBootTest
+@ContextConfiguration(classes = [DmiProperties, DmiRestClient, ObjectMapper])
class DmiRestClientSpec extends Specification {
- def mockDmiProperties = Mock(NcmpConfiguration.DmiProperties)
- def mockRestTemplate = Mock(RestTemplate)
- def objectUnderTest = new DmiRestClient(mockRestTemplate, mockDmiProperties)
+ @SpringBean
+ RestTemplate mockRestTemplate = Mock(RestTemplate)
+
+ @Autowired
+ NcmpConfiguration.DmiProperties dmiProperties
+
+ @Autowired
+ DmiRestClient objectUnderTest
- def 'DMI PUT operation.'() {
- given: 'a PUT url'
- def getResourceDataUrl = 'http://some-uri/getResourceDataUrl'
- and: 'dmi properties'
- setupTestConfigurationData()
- and: 'the rest template returns a valid response entity'
- def mockResponseEntity = Mock(ResponseEntity)
- mockRestTemplate.exchange(getResourceDataUrl, HttpMethod.PUT, _ as HttpEntity, Object.class) >> mockResponseEntity
- when: 'PUT operation is invoked'
- def result = objectUnderTest.putOperationWithJsonData(getResourceDataUrl, 'json-data', new HttpHeaders())
+ @Autowired
+ ObjectMapper objectMapper
+
+ def responseFromRestTemplate = Mock(ResponseEntity)
+
+ def 'DMI POST operation with JSON.'() {
+ given: 'the rest template returns a valid response entity for the expected parameters'
+ mockRestTemplate.postForEntity('my url', _ as HttpEntity, Object.class) >> responseFromRestTemplate
+ when: 'POST operation is invoked'
+ def result = objectUnderTest.postOperationWithJsonData('my url', 'some json', READ)
then: 'the output of the method is equal to the output from the test template'
- result == mockResponseEntity
+ result == responseFromRestTemplate
}
- def 'DMI POST operation.'() {
- given: 'a POST url'
- def getResourceDataUrl = 'http://some-uri/createResourceDataUrl'
- and: 'dmi properties'
- setupTestConfigurationData()
- and: 'the rest template returns a valid response entity'
- def mockResponseEntity = Mock(ResponseEntity)
- mockRestTemplate.postForEntity(getResourceDataUrl, _ as HttpEntity, Void.class) >> mockResponseEntity
+ def 'Failing DMI POST operation.'() {
+ given: 'the rest template returns a valid response entity'
+ def serverResponse = 'server response'.getBytes()
+ def httpServerErrorException = new HttpServerErrorException(HttpStatus.FORBIDDEN, 'status text', serverResponse, null)
+ mockRestTemplate.postForEntity(*_) >> { throw httpServerErrorException }
when: 'POST operation is invoked'
- def result = objectUnderTest.postOperationWithJsonData(getResourceDataUrl, 'json-data', new HttpHeaders())
- then: 'the output of the method is equal to the output from the test template'
- result == mockResponseEntity
+ def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation)
+ then: 'a Http Client Exception is thrown'
+ def thrown = thrown(HttpClientRequestException)
+ and: 'the exception has the relevant details from the error response'
+ assert thrown.httpStatus == 403
+ assert thrown.message == "Unable to ${operation} resource data."
+ assert thrown.details == 'server response'
+ where: 'the following operation is executed'
+ operation << [CREATE, READ, PATCH]
+ }
+
+ def 'Dmi trust level is determined by spring boot health status'() {
+ given: 'a health check response'
+ def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
+ def jsonNode = objectMapper.readValue(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
+ ((ObjectNode) jsonNode).put('status', 'my status')
+ mockRestTemplate.getForObject(*_) >> {jsonNode}
+ when: 'get trust level of the dmi plugin'
+ def result = objectUnderTest.getDmiHealthStatus('some url')
+ then: 'the status value from the json is return'
+ assert result == 'my status'
}
- def setupTestConfigurationData() {
- mockDmiProperties.authUsername >> 'some-username'
- mockDmiProperties.authPassword >> 'some-password'
+ def 'Failing to get dmi plugin health status #scenario'() {
+ given: 'rest template with #scenario'
+ mockRestTemplate.getForObject(*_) >> healthStatusResponse
+ when: 'attempt to get health status of the dmi plugin'
+ def result = objectUnderTest.getDmiHealthStatus('some url')
+ then: 'result will be empty'
+ assert result == ''
+ where: 'the following responses are used'
+ scenario | healthStatusResponse
+ 'null' | null
+ 'exception' | {throw new Exception()}
}
-}
\ No newline at end of file
+
+ def 'Basic auth header #scenario'() {
+ when: 'Specific dmi properties are provided'
+ dmiProperties.dmiBasicAuthEnabled = authEnabled
+ then: 'http headers to conditionally have Authorization header'
+ assert (objectUnderTest.configureHttpHeaders(new HttpHeaders()).get('Authorization') != null) == isPresentInHttpHeader
+ where: 'the following configurations are used'
+ scenario | authEnabled || isPresentInHttpHeader
+ 'auth enabled' | true || true
+ 'auth disabled' | false || false
+ }
+
+}