From c457ba316cbd9280574ca67605048b85f775e0a3 Mon Sep 17 00:00:00 2001 From: sourabh_sourabh Date: Tue, 11 Jun 2024 08:56:54 +0100 Subject: #2: Used async version of web client for single cm handle read operation - Code change is done to use async web client for single cm handle read data operation. - CpsNcmpTaskExecutor class and groovy test code is removed. - Use of supplier code is removed from cm handle Query service. Issue-ID:CPS-2259 Change-Id: I2b7a36e8a151a9224937afd876fceb30be6a24ce Signed-off-by: sourabh_sourabh --- .../controller/NetworkCmProxyControllerSpec.groovy | 25 +++--- .../NcmpDatastoreRequestHandlerSpec.groovy | 36 ++++---- .../NetworkCmProxyRestExceptionHandlerSpec.groovy | 4 - .../rest/executor/CpsNcmpTaskExecutorSpec.groovy | 99 ---------------------- 4 files changed, 29 insertions(+), 135 deletions(-) delete mode 100644 cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/executor/CpsNcmpTaskExecutorSpec.groovy (limited to 'cps-ncmp-rest/src/test/groovy/org/onap') diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index c9dbc291c6..3a5748f002 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -59,7 +59,6 @@ import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.ncmp.api.models.CmResourceAddress import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler -import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper import org.onap.cps.ncmp.rest.model.DataOperationDefinition @@ -82,6 +81,9 @@ import spock.lang.Specification import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter +import groovy.json.JsonSlurper +import org.springframework.http.ResponseEntity +import reactor.core.publisher.Mono @WebMvcTest(NetworkCmProxyController) class NetworkCmProxyControllerSpec extends Specification { @@ -113,17 +115,14 @@ class NetworkCmProxyControllerSpec extends Specification { @SpringBean Map trustLevelPerCmHandle = [:] - @SpringBean - CpsNcmpTaskExecutor mockCpsTaskExecutor = Mock() - @SpringBean DeprecationHelper stubbedDeprecationHelper = Stub() @SpringBean - NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler = new NcmpCachedResourceRequestHandler(mockCpsTaskExecutor, mockNetworkCmProxyDataService, mockNetworkCmProxyQueryService) + NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler = new NcmpCachedResourceRequestHandler(mockNetworkCmProxyDataService, mockNetworkCmProxyQueryService) @SpringBean - NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler = new NcmpPassthroughResourceRequestHandler(mockCpsTaskExecutor, mockNetworkCmProxyDataService) + NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler = new NcmpPassthroughResourceRequestHandler(mockNetworkCmProxyDataService) @Value('${rest.api.ncmp-base-path}/v1') def ncmpBasePathV1 @@ -160,7 +159,7 @@ class NetworkCmProxyControllerSpec extends Specification { when: 'get data resource request is performed' def response = mvc.perform(get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response then: 'the NCMP data service is called with correct parameters' - 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(expectedCmResourceAddress, '(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) + 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(expectedCmResourceAddress, '(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >> Mono.just(new ResponseEntity(HttpStatus.OK)) and: 'response status is Ok' assert response.status == HttpStatus.OK.value() } @@ -253,13 +252,15 @@ class NetworkCmProxyControllerSpec extends Specification { def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=$resourceIdentifier&options=(a=1,b=2)" and: 'ncmp service returns json object' def expectedCmResourceAddress = new CmResourceAddress(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle', resourceIdentifier) - mockNetworkCmProxyDataService.getResourceDataForCmHandle(expectedCmResourceAddress,'(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >> '{valid-json}' + 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(expectedCmResourceAddress, '(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) + >> Mono.just(new ResponseEntity('{valid-json}', HttpStatus.OK)) when: 'get data resource request is performed' def response = mvc.perform(get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response then: 'response status is Ok' - response.status == HttpStatus.OK.value() - and: 'response contains valid object body' - response.getContentAsString() == '{valid-json}' + assert response.status == 200 + and: 'response contains the object returned by the service' + def responseAsJsonObject = new JsonSlurper().parseText(response.getContentAsString()) + assert responseAsJsonObject.body == '{valid-json}' where: 'tokens are used in the resource identifier parameter' scenario | resourceIdentifier '/' | 'id/with/slashes' @@ -452,6 +453,8 @@ class NetworkCmProxyControllerSpec extends Specification { def 'Get resource data from DMI with valid topic i.e. async request for #scenario'() { given: 'resource data url' def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name" + and: 'the NCMP data service is called with correct parameters' + 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(_, '(a=1,b=2)', 'my-topic-name', _, NO_AUTH_HEADER) >> Mono.just(new ResponseEntity(HttpStatus.OK)) when: 'get data resource request is performed' def response = mvc.perform(get(getUrl).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON_VALUE)).andReturn().response then: 'async request id is generated' diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy index 8835c99fb1..00b0cb04c5 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy @@ -28,16 +28,16 @@ import org.onap.cps.ncmp.api.models.DataOperationRequest import org.onap.cps.ncmp.api.models.CmResourceAddress import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException import org.onap.cps.ncmp.rest.exceptions.PayloadTooLargeException -import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor +import org.springframework.http.HttpStatus +import reactor.core.publisher.Mono import spock.lang.Specification import spock.util.concurrent.PollingConditions class NcmpDatastoreRequestHandlerSpec extends Specification { - def spiedCpsNcmpTaskExecutor = Spy(CpsNcmpTaskExecutor) def mockNetworkCmProxyDataService = Mock(NetworkCmProxyDataService) - def objectUnderTest = new NcmpPassthroughResourceRequestHandler(spiedCpsNcmpTaskExecutor, mockNetworkCmProxyDataService) + def objectUnderTest = new NcmpPassthroughResourceRequestHandler(mockNetworkCmProxyDataService) def NO_AUTH_HEADER = null @@ -48,32 +48,26 @@ class NcmpDatastoreRequestHandlerSpec extends Specification { def 'Attempt to execute async get request with #scenario.'() { given: 'notification feature is turned on/off' objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled - and: 'a flag to track the network service call' - def networkServiceMethodCalled = false and: 'a CM resource address' def cmResourceAddress = new CmResourceAddress('ds', 'ch1', 'resource1') - and: 'the (mocked) service will use the flag to indicate if it is called' - mockNetworkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, 'options', _, _, NO_AUTH_HEADER) >> - { networkServiceMethodCalled = true } + and: 'the (mocked) service is called with the correct parameters returns OK' + 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, 'options', _, _, NO_AUTH_HEADER) >> Mono.just(HttpStatus.OK) when: 'get request is executed with topic = #topic' - objectUnderTest.executeRequest(cmResourceAddress, 'options', topic, false, NO_AUTH_HEADER) - then: 'the task is executed in an async fashion or not' - expectedCalls * spiedCpsNcmpTaskExecutor.executeTask(*_) - and: 'the service request is invoked' - new PollingConditions().within(1) { - assert networkServiceMethodCalled == true - } + def response= objectUnderTest.executeRequest(cmResourceAddress, 'options', topic, false, NO_AUTH_HEADER) + then: 'a successful response with/without request id is returned' + assert response.statusCode.value == 200 + assert response.body instanceof Map == expectedResponseBodyIsMap where: 'the following parameters are used' - scenario | notificationFeatureEnabled | topic || expectedCalls - 'feature on, valid topic' | true | 'valid' || 1 - 'feature on, no topic' | true | null || 0 - 'feature off, valid topic' | false | 'valid' || 0 - 'feature off, no topic' | false | null || 0 + scenario | notificationFeatureEnabled | topic || expectedCalls | expectedResponseBodyIsMap + 'feature on, valid topic' | true | 'valid' || 1 | true + 'feature on, no topic' | true | null || 0 | false + 'feature off, valid topic' | false | 'valid' || 0 | false + 'feature off, no topic' | false | null || 0 | false } def 'Attempt to execute async data operation request with feature #scenario.'() { given: 'a extended request handler that supports bulk requests' - def objectUnderTest = new NcmpPassthroughResourceRequestHandler(spiedCpsNcmpTaskExecutor, mockNetworkCmProxyDataService) + def objectUnderTest = new NcmpPassthroughResourceRequestHandler(mockNetworkCmProxyDataService) and: 'notification feature is turned on/off' objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled when: 'data operation request is executed' diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index ea472cd931..33eb48ffa2 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -43,7 +43,6 @@ import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler -import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper import org.onap.cps.ncmp.rest.util.DeprecationHelper @@ -82,9 +81,6 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { @SpringBean DataOperationRequestMapper dataOperationRequestMapper = Mappers.getMapper(DataOperationRequestMapper) - @SpringBean - CpsNcmpTaskExecutor stubbedCpsTaskExecutor = Stub() - @SpringBean DeprecationHelper stubbedDeprecationHelper = Stub() diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/executor/CpsNcmpTaskExecutorSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/executor/CpsNcmpTaskExecutorSpec.groovy deleted file mode 100644 index 4c8c40f4e6..0000000000 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/executor/CpsNcmpTaskExecutorSpec.groovy +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.rest.executor - -import ch.qos.logback.classic.Level -import ch.qos.logback.classic.Logger -import ch.qos.logback.classic.spi.ILoggingEvent -import ch.qos.logback.core.read.ListAppender -import org.slf4j.LoggerFactory -import spock.lang.Specification -import spock.util.concurrent.PollingConditions - -class CpsNcmpTaskExecutorSpec extends Specification { - - def objectUnderTest = new CpsNcmpTaskExecutor() - def logger = Spy(ListAppender) - def enoughTime = 100 - def notEnoughTime = 10 - - void setup() { - ((Logger) LoggerFactory.getLogger(CpsNcmpTaskExecutor.class)).addAppender(logger) - logger.start() - } - - void cleanup() { - ((Logger) LoggerFactory.getLogger(CpsNcmpTaskExecutor.class)).detachAndStopAllAppenders() - } - - def 'Execute successful task.'() { - when: 'task is executed' - objectUnderTest.executeTask(taskSupplier(), enoughTime) - then: 'an event is logged with level INFO' - new PollingConditions().within(1) { - def loggingEvent = getLoggingEvent() - assert loggingEvent.level == Level.INFO - } - and: 'the log indicates the task completed successfully' - assert loggingEvent.formattedMessage == 'Async task completed successfully.' - } - - def 'Execute failing task.'() { - when: 'task is executed' - objectUnderTest.executeTask(taskSupplierForFailingTask(), enoughTime) - then: 'an event is logged with level ERROR' - new PollingConditions().within(1) { - def loggingEvent = getLoggingEvent() - assert loggingEvent.level == Level.ERROR - } - and: 'the original error message is logged' - assert loggingEvent.formattedMessage.contains('original exception message') - } - - def 'Task times out.'() { - when: 'task is executed without enough time to complete' - objectUnderTest.executeTask(taskSupplierForLongRunningTask(), notEnoughTime) - then: 'an event is logged with level ERROR' - new PollingConditions().within(1) { - def loggingEvent = getLoggingEvent() - assert loggingEvent.level == Level.ERROR - } - and: 'a timeout error message is logged' - assert loggingEvent.formattedMessage.contains('java.util.concurrent.TimeoutException') - } - - def taskSupplier() { - return () -> 'hello world' - } - - def taskSupplierForFailingTask() { - return () -> { throw new RuntimeException('original exception message') } - } - - def taskSupplierForLongRunningTask() { - return () -> { sleep(enoughTime) } - } - - def getLoggingEvent() { - return logger.list[0] - } - -} -- cgit 1.2.3-korg