From fa72b5ffde0f6d29a7f7cb3edbff4a7998894017 Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Fri, 9 Jan 2026 16:41:34 +0000 Subject: [PATCH] Demo improvement: output request details as nice json in Policy Executor Stub Issue-ID: CPS-2826 Change-Id: Ia67f3cd8086a58ef0daad308fca9f326edb60b2f Signed-off-by: ToineSiebelink --- .../ncmp/impl/provmns/ParameterHelperSpec.groovy | 4 +-- .../controller/PolicyExecutorStubController.java | 13 +++++++++ .../PolicyExecutorStubControllerSpec.groovy | 33 ++++++++++++++++------ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy index 238bfdbac5..eb8cd118c2 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy @@ -86,7 +86,7 @@ class ParameterHelperSpec extends Specification { } def 'Extract Fdn.'() { - expect: 'Only valid name-id pairs are retuned up to the required index' + expect: 'Only valid name-id pairs are returned up to the required index' assert objectUnderTest.extractFdn('/a=1/b=2/c=3/d/e/f', indexFromEnd) == expectedResult where: 'following fdns are used' indexFromEnd || expectedResult @@ -98,7 +98,7 @@ class ParameterHelperSpec extends Specification { } def 'Extract Parent Fdn.'() { - expect: 'Teh cortect Parent FDN (up to 2nd last name-id pair)) is returned' + expect: 'The correct Parent FDN (up to 2nd last name-id pair)) is returned' assert objectUnderTest.extractParentFdn('/a=1/b=2/c=3/d/e/f') == '/a=1/b=2' } diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java index 4d85592bdb..91348a086d 100644 --- a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java +++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java @@ -20,6 +20,8 @@ package org.onap.cps.policyexecutor.stub.controller; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; @@ -41,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController; public class PolicyExecutorStubController implements OperationPermissionApi { private final Sleeper sleeper; + private final ObjectMapper objectMapper; private static final Pattern PATTERN_SIMULATION = Pattern.compile("policySimulation=(\\w+_\\w+)"); private static final Pattern PATTERN_HTTP_ERROR = Pattern.compile("httpError_(\\d{3})"); @@ -55,6 +58,7 @@ public class PolicyExecutorStubController implements OperationPermissionApi { final String accept, final String authorization) { log.info("Stub Policy Executor Invoked"); + log.info("Permission Request: {}", formatPermissionRequest(permissionRequest)); if (permissionRequest.getOperations().isEmpty()) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } @@ -101,4 +105,13 @@ public class PolicyExecutorStubController implements OperationPermissionApi { return ResponseEntity.ok(new PermissionResponse(id, permissionResult, message)); } + private String formatPermissionRequest(final PermissionRequest permissionRequest) { + try { + return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(permissionRequest); + } catch (final JsonProcessingException jsonProcessingException) { + log.error("Error while formatting permission request", jsonProcessingException); + return "invalid json"; + } + } + } diff --git a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy index 1bda3c2423..c874287e85 100644 --- a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy +++ b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy @@ -20,7 +20,9 @@ package org.onap.cps.policyexecutor.stub.controller +import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.ObjectWriter import org.onap.cps.policyexecutor.stub.model.Operation import org.onap.cps.policyexecutor.stub.model.PermissionRequest import org.onap.cps.policyexecutor.stub.model.PermissionResponse @@ -40,11 +42,11 @@ class PolicyExecutorStubControllerSpec extends Specification { @Autowired MockMvc mockMvc - @Autowired - ObjectMapper objectMapper + @SpringBean + ObjectMapper spiedObjectMapper = Spy(new ObjectMapper()) @SpringBean - Sleeper sleeper = Spy() + Sleeper spiedSleeper = Spy() def url = '/operation-permission/v1/permissions' @@ -61,7 +63,7 @@ class PolicyExecutorStubControllerSpec extends Specification { assert response.status == HttpStatus.OK.value() and: 'the response body has the expected decision details' def responseBody = response.contentAsString - def permissionResponse = objectMapper.readValue(responseBody, PermissionResponse.class) + def permissionResponse = spiedObjectMapper.readValue(responseBody, PermissionResponse.class) assert permissionResponse.id == expectedId assert permissionResponse.permissionResult == expectedResult assert permissionResponse.message == expectedMessage @@ -71,7 +73,6 @@ class PolicyExecutorStubControllerSpec extends Specification { 'prefix/policySimulation=slowResponse_1' || '2' | 'allow' | 'all good' 'prefix/policySimulation=policyResponse_deny' || '3' | 'deny' | 'Stub is mocking a policy response: deny' 'prefix/policySimulation=policyResponse_other' || '4' | 'other' | 'Stub is mocking a policy response: other' - } def 'Permission request with a HTTP error code.'() { @@ -102,7 +103,7 @@ class PolicyExecutorStubControllerSpec extends Specification { def 'Permission request with no operations.'() { given: 'a permission request with no operations' def permissionRequest = new PermissionRequest('some decision type', []) - def requestBody = objectMapper.writeValueAsString(permissionRequest) + def requestBody = spiedObjectMapper.writeValueAsString(permissionRequest) when: 'request is posted' def response = mockMvc.perform(post(url) .header('Authorization','some string') @@ -124,10 +125,26 @@ class PolicyExecutorStubControllerSpec extends Specification { assert response.status == HttpStatus.BAD_REQUEST.value() } + def 'Exception thrown while printing pretty json.'() { + given: 'object writer for pretty json throws an exception' + def mockObjectWriter = Mock(ObjectWriter) + spiedObjectMapper.writerWithDefaultPrettyPrinter() >> mockObjectWriter + mockObjectWriter.writeValueAsString(_) >> { throw new JsonProcessingException('test') } + when: 'request is posted' + def response = mockMvc.perform(post(url) + .header('Authorization','some string') + .contentType(MediaType.APPLICATION_JSON) + .content(createRequestBody('some fdn'))) + .andReturn().response + then: 'response status is OK (exception is ignored)' + assert response.status == HttpStatus.OK.value() + } + + def 'Permission request with interrupted exception during slow response.'() { given: 'a permission request with a target fdn to simulate a slow response' def requestBody = createRequestBody('policySimulation=slowResponse_5') - sleeper.haveALittleRest(_) >> { throw new InterruptedException() } + spiedSleeper.haveALittleRest(_) >> { throw new InterruptedException() } when: 'request is posted' mockMvc.perform(post(url) .header('Authorization','some string') @@ -164,7 +181,7 @@ class PolicyExecutorStubControllerSpec extends Specification { operation.setChangeRequest(changeRequest) operation.setResourceIdentifier(resourceIdentifier) def permissionRequest = new PermissionRequest('cm-legacy', [operation]) - return objectMapper.writeValueAsString(permissionRequest) + return spiedObjectMapper.writeValueAsString(permissionRequest) } } -- 2.16.6