Demo improvement: output request details as nice json in Policy Executor Stub 97/142897/2
authorToineSiebelink <toine.siebelink@est.tech>
Fri, 9 Jan 2026 16:41:34 +0000 (16:41 +0000)
committerToineSiebelink <toine.siebelink@est.tech>
Mon, 12 Jan 2026 10:29:09 +0000 (10:29 +0000)
Issue-ID: CPS-2826
Change-Id: Ia67f3cd8086a58ef0daad308fca9f326edb60b2f
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy
policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy

index 238bfdb..eb8cd11 100644 (file)
@@ -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'
     }
 
index 4d85592..91348a0 100644 (file)
@@ -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";
+        }
+    }
+
 }
index 1bda3c2..c874287 100644 (file)
@@ -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)
     }
 
 }