- scenario | additionalProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl
- 'without properties' | [] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
- 'null properties' | null | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
- 'with properties' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
- 'null options' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
- 'empty options' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
- 'datastore running' | [] | PASSTHROUGH_RUNNING | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)'
+ scenario | dmiProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl
+ 'without properties' | [] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
+ 'with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
+ 'null options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
+ 'empty options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
+ 'datastore running without properties' | [] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)'
+ 'datastore running with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-running' | '&options=(a=1,b=2)'
+ }
+
+ def 'Execute (async) data operation from DMI service.'() {
+ given: 'collection of yang model cm Handles and data operation request'
+ mockYangModelCmHandleCollectionRetrieval([yangModelCmHandleProperty])
+ def dataOperationBatchRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
+ def dataOperationRequest = spiedJsonObjectMapper.convertJsonString(dataOperationBatchRequestJsonData, DataOperationRequest.class)
+ dataOperationRequest.dataOperationDefinitions[0].cmHandleIds = [cmHandleId]
+ def requestBodyAsJsonStringArg = null
+ and: 'a positive response from DMI service when it is called with valid request parameters'
+ def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
+ def expectedDmiBatchResourceDataUrl = "ncmp/v1/data/topic=my-topic-name"
+ def expectedBatchRequestAsJson = '[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","cmHandleProperties":{"prop1":"val1"}}]}]'
+ mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName) >> responseFromDmi
+ dmiServiceUrlBuilder.getDataOperationRequestUrl(_, _) >> expectedDmiBatchResourceDataUrl
+ when: 'get resource data for group of cm handles are invoked'
+ objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'requestId')
+ then: 'wait a little to allow execution of service method by task executor (on separate thread)'
+ Thread.sleep(100)
+ then: 'validate ncmp generated dmi request body json args'
+ 1 * mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ) >> { args -> requestBodyAsJsonStringArg = args[1] }
+ assert requestBodyAsJsonStringArg == expectedBatchRequestAsJson
+ }
+
+ def 'Execute (async) data operation from DMI service for #scenario.'() {
+ given: 'data operation request body and dmi resource url'
+ def dmiDataOperation = DmiDataOperation.builder().operationId('some-operation-id').build()
+ dmiDataOperation.getCmHandles().add(CmHandle.builder().id('some-cm-handle-id').build())
+ def dmiDataOperationResourceDataUrl = "http://dmi-service-name:dmi-port/dmi/v1/data?topic=my-topic-name&requestId=some-request-id"
+ def actualDataOperationCloudEvent = null
+ when: 'exception occurs after sending request to dmi service'
+ objectUnderTest.handleTaskCompletionException(new Throwable(exception), dmiDataOperationResourceDataUrl, List.of(dmiDataOperation))
+ then: 'a cloud event is published'
+ eventsPublisher.publishCloudEvent('my-topic-name', 'some-request-id', _) >> { args -> actualDataOperationCloudEvent = args[2] }
+ and: 'the event contains the expected error details'
+ def eventDataValue = extractDataValue(actualDataOperationCloudEvent)
+ assert eventDataValue.operationId == dmiDataOperation.operationId
+ assert eventDataValue.ids == dmiDataOperation.cmHandles.id
+ assert eventDataValue.statusCode == responseCode.statusCode
+ assert eventDataValue.statusMessage == responseCode.statusMessage
+ where: 'the following exceptions are occurred'
+ scenario | exception || responseCode
+ 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA
+ 'timeout exception' | new TimeoutException() || NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING
+ }
+
+ def 'call get all resource data.'() {
+ given: 'the system returns a cm handle with a sample property'
+ mockYangModelCmHandleRetrieval([yangModelCmHandleProperty])
+ and: 'a positive response from DMI service when it is called with the expected parameters'
+ def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
+ def expectedUrl = dmiServiceBaseUrl + "passthrough-operational?resourceIdentifier=/"
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}', READ) >> responseFromDmi
+ dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
+ when: 'get resource data is invoked'
+ def result = objectUnderTest.getResourceDataFromDmi( PASSTHROUGH_OPERATIONAL.datastoreName, cmHandleId, NO_REQUEST_ID)
+ then: 'the result is the response from the DMI service'
+ assert result == responseFromDmi