From bb030cb7803d3d08f86de5eb1c6be5ad32f5fbf6 Mon Sep 17 00:00:00 2001 From: "puthuparambil.aditya" Date: Tue, 1 Mar 2022 11:51:20 +0000 Subject: [PATCH] Bug fix for delete data node not working for root node Fixing event for deletion of container node Fixing event for deletion of root node when '' is passed as xpath Issue-ID: CPS-895 Signed-off-by: puthuparambil.aditya Change-Id: I0676aec29e7b7e12bef2300219207ddc22414daa --- .../spi/impl/CpsDataPersistenceServiceImpl.java | 4 +- .../onap/cps/notification/NotificationService.java | 12 ++++-- .../notification/NotificationServiceSpec.groovy | 44 +++++++++------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index f22d83b98..78862d723 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -337,7 +337,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService deleteDataNodes(dataspaceName, anchorName); targetDeleted = true; } else { - if (isContainerNodeXpath(targetXpath)) { + if (isRootContainerNodeXpath(targetXpath)) { parentNodeXpath = targetXpath; } else { parentNodeXpath = targetXpath.substring(0, targetXpath.lastIndexOf('/')); @@ -423,7 +423,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService return !existingListElementsByXpath.containsKey(replacementDataNode.getXpath()); } - private static boolean isContainerNodeXpath(final String xpath) { + private static boolean isRootContainerNodeXpath(final String xpath) { return 0 == xpath.lastIndexOf('/'); } diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java index 5ad59df2a..5e26a2204 100644 --- a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java +++ b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java @@ -37,8 +37,6 @@ import org.springframework.stereotype.Service; @Slf4j public class NotificationService { - private static final String ROOT_NODE_XPATH = "/"; - private NotificationProperties notificationProperties; private NotificationPublisher notificationPublisher; private CpsDataUpdatedEventFactory cpsDataUpdatedEventFactory; @@ -120,7 +118,15 @@ public class NotificationService { } private Operation getRootNodeOperation(final String xpath, final Operation operation) { - return ROOT_NODE_XPATH.equals(xpath) ? operation : Operation.UPDATE; + return isRootXpath(xpath) || isRootContainerNodeXpath(xpath) ? operation : Operation.UPDATE; + } + + private static boolean isRootXpath(final String xpath) { + return "/".equals(xpath) || "".equals(xpath); + } + + private static boolean isRootContainerNodeXpath(final String xpath) { + return 0 == xpath.lastIndexOf('/'); } } diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy index c20bdeea7..6ef6874b3 100644 --- a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy @@ -90,35 +90,15 @@ class NotificationServiceSpec extends Specification { 'dataspace name matches filter' | 'my-dataspace-published' || 1 } - def 'Send UPDATE operation when non-root data nodes are changed.'() { - given: 'notification is enabled' - spyNotificationProperties.isEnabled() >> true - and: 'event factory creates event if operation is UPDATE' - def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, - Operation.UPDATE) >> cpsDataUpdatedEvent - when: 'dataUpdatedEvent is received for non-root xpath' - def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, '/non-root-node', - operation) - and: 'wait for async processing to complete' - future.get(10, TimeUnit.SECONDS) - then: 'async process completed successfully' - future.isDone() - and: 'notification is sent' - 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) - where: - operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] - } - - def 'Send same operation when root nodes are changed.'() { + def '#scenario are changed with xpath #xpath and operation #operation'() { given: 'notification is enabled' spyNotificationProperties.isEnabled() >> true and: 'event factory creates event if operation is #operation' def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, operation) >> + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, expectedOperationInEvent) >> cpsDataUpdatedEvent - when: 'dataUpdatedEvent is received for root xpath' - def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, '/', operation) + when: 'dataUpdatedEvent is received for #xpath' + def future = objectUnderTest.processDataUpdatedEvent(anchor, myObservedTimestamp, xpath, operation) and: 'wait for async processing to complete' future.get(10, TimeUnit.SECONDS) then: 'async process completed successfully' @@ -126,10 +106,21 @@ class NotificationServiceSpec extends Specification { and: 'notification is sent' 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) where: - operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] + scenario | xpath | operation || expectedOperationInEvent + 'Same event is sent when root nodes' | '' | Operation.CREATE || Operation.CREATE + 'Same event is sent when root nodes' | '' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when root nodes' | '' | Operation.DELETE || Operation.DELETE + 'Same event is sent when root nodes' | '/' | Operation.CREATE || Operation.CREATE + 'Same event is sent when root nodes' | '/' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when root nodes' | '/' | Operation.DELETE || Operation.DELETE + 'Same event is sent when container nodes' | '/parent' | Operation.CREATE || Operation.CREATE + 'Same event is sent when container nodes' | '/parent' | Operation.UPDATE || Operation.UPDATE + 'Same event is sent when container nodes' | '/parent' | Operation.DELETE || Operation.DELETE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.CREATE || Operation.UPDATE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.UPDATE || Operation.UPDATE + 'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.DELETE || Operation.UPDATE } - def 'Error handling in notification service.'() { given: 'notification is enabled' spyNotificationProperties.isEnabled() >> true @@ -146,5 +137,4 @@ class NotificationServiceSpec extends Specification { notThrown Exception 1 * spyNotificationErrorHandler.onException(_, _, _, '/', Operation.CREATE) } - } -- 2.16.6