aboutsummaryrefslogtreecommitdiffstats
path: root/cps-service/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'cps-service/src/test')
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy10
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy166
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy8
-rw-r--r--cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang48
4 files changed, 223 insertions, 9 deletions
diff --git a/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
index 5dee8fc28b..6d9ff12060 100644
--- a/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/events/CpsDataUpdateEventsServiceSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* Copyright (C) 2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +25,7 @@ import static org.onap.cps.events.model.Data.Operation.CREATE
import static org.onap.cps.events.model.Data.Operation.DELETE
import static org.onap.cps.events.model.Data.Operation.UPDATE
+import org.onap.cps.api.CpsNotificationService
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import io.cloudevents.core.CloudEventUtils
@@ -41,8 +42,13 @@ import java.time.OffsetDateTime
class CpsDataUpdateEventsServiceSpec extends Specification {
def mockEventsPublisher = Mock(EventsPublisher)
def objectMapper = new ObjectMapper();
+ def mockCpsNotificationService = Mock(CpsNotificationService)
- def objectUnderTest = new CpsDataUpdateEventsService(mockEventsPublisher)
+ def objectUnderTest = new CpsDataUpdateEventsService(mockEventsPublisher, mockCpsNotificationService)
+
+ def setup() {
+ mockCpsNotificationService.isNotificationEnabled('dataspace01', 'anchor01') >> true
+ }
def 'Create and Publish cps update event where events are #scenario'() {
given: 'an anchor, operation and observed timestamp'
diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy
new file mode 100644
index 0000000000..0f563272d1
--- /dev/null
+++ b/cps-service/src/test/groovy/org/onap/cps/impl/CpsNotificationServiceImplSpec.groovy
@@ -0,0 +1,166 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 TechMahindra Ltd.
+ * ================================================================================
+ * 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.impl
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.api.CpsAnchorService
+import org.onap.cps.api.exceptions.DataNodeNotFoundException
+import org.onap.cps.api.exceptions.DataValidationException
+import org.onap.cps.api.model.Anchor
+import org.onap.cps.api.parameters.FetchDescendantsOption;
+import org.onap.cps.spi.CpsDataPersistenceService
+import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.PrefixResolver
+import org.onap.cps.utils.YangParser
+import org.onap.cps.TestUtils
+import org.onap.cps.utils.YangParserHelper
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
+import org.onap.cps.yang.YangTextSchemaSourceSet
+import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
+import org.springframework.test.context.ContextConfiguration
+
+import spock.lang.Specification
+
+@ContextConfiguration(classes = [ObjectMapper, JsonObjectMapper])
+class CpsNotificationServiceImplSpec extends Specification {
+
+ def dataspaceName = 'CPS-Admin'
+ def anchorName = 'cps-notification-subscriptions'
+ def schemaSetName = 'cps-notification-subscriptions'
+ def anchor = new Anchor(anchorName, dataspaceName, schemaSetName)
+
+ def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def mockCpsAnchorService = Mock(CpsAnchorService)
+ def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+ def mockTimedYangTextSchemaSourceSetBuilder = Mock(TimedYangTextSchemaSourceSetBuilder)
+ def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache, mockTimedYangTextSchemaSourceSetBuilder)
+ def mockPrefixResolver = Mock(PrefixResolver)
+ def objectUnderTest = new CpsNotificationServiceImpl(mockCpsAnchorService, mockCpsDataPersistenceService, yangParser, mockPrefixResolver)
+
+ def 'add notification subscription for list of dataspaces'() {
+ given: 'details for notification subscription and subscription root node xpath'
+ def notificationSubscriptionAsjson = '{"dataspace":[{"name":"ds01"},{"name":"ds02"}]}'
+ def xpath = '/dataspaces'
+ and: 'schema set for given anchor and dataspace references notification subscription model'
+ setupSchemaSetMocks('cps-notification-subscriptions@2024-07-03.yang')
+ and: 'anchor is provided'
+ mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> anchor
+ when: 'create notification subscription is called'
+ objectUnderTest.createNotificationSubscription(notificationSubscriptionAsjson, xpath)
+ then: 'the persistence service is called once with the correct parameters'
+ 1 * mockCpsDataPersistenceService.addListElements('CPS-Admin', 'cps-notification-subscriptions', xpath, { dataNodeCollection ->
+ {
+ assert dataNodeCollection.size() == 2
+ assert dataNodeCollection.collect { it.getXpath() }
+ .containsAll(['/dataspaces/dataspace[@name=\'ds01\']', '/dataspaces/dataspace[@name=\'ds02\']'])
+ }
+ })
+ }
+
+ def 'add notification subscription fails with exception'() {
+ given: 'details for notification subscription'
+ def jsonData = '{"dataspace":[{"name":"ds01"},{"name":"ds02"}]}'
+ and: 'schema set for given anchor and dataspace references invalid data model'
+ setupSchemaSetMocks('test-tree.yang')
+ and: 'anchor is provided'
+ mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> anchor
+ when: 'create notification subscription is called'
+ objectUnderTest.createNotificationSubscription(jsonData, '/somepath')
+ then: 'data validation exception is thrown '
+ thrown(DataValidationException)
+ }
+
+ def 'delete notification subscription for given xpath'() {
+ given: 'details for notification subscription'
+ def xpath = '/some/path'
+ when: 'delete notification subscription is called'
+ objectUnderTest.deleteNotificationSubscription(xpath)
+ then: 'the persistence service is called once with the correct parameters'
+ 1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, xpath)
+ }
+
+ def 'get notification subscription for given xpath'() {
+ given: 'details for notification subscription'
+ def xpath = '/some/path'
+ and: 'persistence service returns data nodes for subscribed data'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName,
+ xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/some/path').withLeaves([leaf: 'dataspace', leafList: ['ds01', 'ds02']]).build()]
+ when: 'delete notification subscription is called'
+ def result = objectUnderTest.getNotificationSubscription(xpath)
+ then: 'the result is a json representation of the data node(s) returned by the data persistence service'
+ assert result.get(0).toString() == '{path={leaf=dataspace, leafList=[ds01, ds02]}}'
+ }
+
+ def 'is notification enabled for given anchor'() {
+ given: 'data nodes available for given anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.isNotificationEnabled(dataspaceName, anchorName)
+ then: 'the notification is enabled'
+ assert isNotificationEnabled
+ }
+
+ def 'is notification disabled for given anchor'() {
+ given: 'data nodes not available for given anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors/anchor[@name='anchor-01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ { throw new DataNodeNotFoundException(dataspaceName, anchorName) }
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.isNotificationEnabled('ds01', 'anchor-01')
+ then: 'the notification is disabled'
+ assert !isNotificationEnabled
+ }
+
+ def 'is notification enabled for all anchors in a dataspace'() {
+ given: 'data nodes available for given dataspace'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ and: 'data nodes not available for any specific anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ { throw new DataNodeNotFoundException(dataspaceName, anchorName) }
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.notificationEnabledForAllAnchors('ds01')
+ then: 'the notification is enabled'
+ assert isNotificationEnabled
+ }
+
+ def 'is notification disabled for all anchors in a dataspace'() {
+ given: 'data nodes available for given dataspace'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ and: 'data nodes also available for any specific anchor'
+ mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, "/dataspaces/dataspace[@name='ds01']/anchors", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >>
+ [new DataNodeBuilder().withXpath('/xpath-1').build()]
+ when: 'is notification enabled is called'
+ boolean isNotificationEnabled = objectUnderTest.notificationEnabledForAllAnchors('ds01')
+ then: 'the notification is disabled'
+ assert !isNotificationEnabled
+ }
+
+ def setupSchemaSetMocks(String... yangResources) {
+ def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
+ mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
+ def yangResourceNameToContent = TestUtils.getYangResourcesAsMap(yangResources)
+ def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
+ mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
+ }
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
index 0d515f90ac..1e2dc54424 100644
--- a/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/init/CpsNotificationSubscriptionModelLoaderSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 TechMahindra Ltd.
+ * Copyright (C) 2024-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,10 +78,4 @@ class CpsNotificationSubscriptionModelLoaderSpec extends Specification {
and: 'the data service to create a top level datanode is called once'
1 * mockCpsDataService.saveData(CPS_DATASPACE_NAME, ANCHOR_NAME, '{"dataspaces":{}}', _)
}
-
- private void assertLogContains(String message) {
- def logs = loggingListAppender.list.toString()
- assert logs.contains(message)
- }
-
}
diff --git a/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang b/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang
new file mode 100644
index 0000000000..1cab7923ea
--- /dev/null
+++ b/cps-service/src/test/resources/cps-notification-subscriptions@2024-07-03.yang
@@ -0,0 +1,48 @@
+module cps-notification-subscriptions {
+ yang-version 1.1;
+ namespace "org:onap:cps";
+
+ prefix cps-notification-subscriptions;
+
+ revision "2024-08-05" {
+ description
+ "First release of cps notification subscriptions model";
+ }
+ container dataspaces {
+
+ list dataspace {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ container anchors {
+
+ list anchor {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ container xpaths {
+
+ list xpath {
+ key "path";
+ leaf path {
+ type string;
+ }
+ }
+ }
+ }
+ }
+ leaf-list subscriptionIds {
+ type string;
+ }
+ leaf topic {
+ type string;
+ }
+ }
+ }
+} \ No newline at end of file