Moving and Renaming eexisting subscription impl
[cps.git] / cps-service / src / test / groovy / org / onap / cps / notification / CpsDataUpdatedEventFactorySpec.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (c) 2021-2022 Bell Canada.
4  *  Modifications Copyright (c) 2022-2023 Nordix Foundation
5  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
6  *  ================================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  SPDX-License-Identifier: Apache-2.0
20  *  ============LICENSE_END=========================================================
21  */
22
23 package org.onap.cps.notification
24
25 import org.onap.cps.spi.model.DataNode
26
27 import java.time.OffsetDateTime
28 import java.time.format.DateTimeFormatter
29 import org.onap.cps.utils.DateTimeUtility
30 import org.onap.cps.utils.PrefixResolver
31 import org.onap.cps.api.CpsDataService
32 import org.onap.cps.event.model.Content
33 import org.onap.cps.event.model.Data
34 import org.onap.cps.spi.FetchDescendantsOption
35 import org.onap.cps.spi.model.Anchor
36 import org.onap.cps.spi.model.DataNodeBuilder
37 import org.springframework.util.StringUtils
38 import spock.lang.Specification
39
40 class CpsDataUpdatedEventFactorySpec extends Specification {
41
42     def mockCpsDataService = Mock(CpsDataService)
43
44     def mockPrefixResolver = Mock(PrefixResolver)
45
46     def objectUnderTest = new CpsDataUpdatedEventFactory(mockCpsDataService, mockPrefixResolver)
47
48     def dateTimeFormat = 'yyyy-MM-dd\'T\'HH:mm:ss.SSSZ'
49
50     def 'Create a CPS data updated event successfully: #scenario'() {
51         given: 'an anchor which has been updated'
52             def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
53         and: 'cps data service returns the data node details'
54             def xpath = '/xpath'
55             def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(['leafName': 'leafValue']).build()
56             mockCpsDataService.getDataNodes(
57                     'my-dataspace', 'my-anchorname', '/', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode]
58         when: 'CPS data updated event is created'
59             def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(anchor,
60                     DateTimeUtility.toOffsetDateTime(inputObservedTimestamp), Operation.CREATE)
61         then: 'CPS data updated event is created with correct envelope'
62             with(cpsDataUpdatedEvent) {
63                 type == 'org.onap.cps.data-updated-event'
64                 source == new URI('urn:cps:org.onap.cps')
65                 schema == new URI('urn:cps:org.onap.cps:data-updated-event-schema:v1')
66                 StringUtils.hasText(id)
67                 content != null
68             }
69         and: 'correct content'
70             with(cpsDataUpdatedEvent.content) {
71                 assert isExpectedDateTimeFormat(observedTimestamp): "$observedTimestamp is not in $dateTimeFormat format"
72                 if (inputObservedTimestamp != null)
73                     assert observedTimestamp == inputObservedTimestamp
74                 else
75                     assert OffsetDateTime.now().minusSeconds(20).isBefore(
76                             DateTimeUtility.toOffsetDateTime(observedTimestamp))
77                 assert anchorName == 'my-anchorname'
78                 assert dataspaceName == 'my-dataspace'
79                 assert schemaSetName == 'my-schemaset-name'
80                 assert operation == Content.Operation.CREATE
81                 assert data == new Data().withAdditionalProperty('xpath', ['leafName': 'leafValue'])
82             }
83         where:
84             scenario                        | inputObservedTimestamp
85             'with observed timestamp -0400' | '2021-01-01T23:00:00.345-0400'
86             'with observed timestamp +0400' | '2021-01-01T23:00:00.345+0400'
87             'missing observed timestamp'    | null
88     }
89
90     def 'Create a delete CPS data updated event successfully'() {
91         given: 'an anchor which has been deleted'
92             def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
93             def deletionTimestamp = '2021-01-01T23:00:00.345-0400'
94         when: 'a delete root data node event is created'
95             def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(anchor,
96                     DateTimeUtility.toOffsetDateTime(deletionTimestamp), Operation.DELETE)
97         then: 'CPS data updated event is created with correct envelope'
98             with(cpsDataUpdatedEvent) {
99                 type == 'org.onap.cps.data-updated-event'
100                 source == new URI('urn:cps:org.onap.cps')
101                 schema == new URI('urn:cps:org.onap.cps:data-updated-event-schema:v1')
102                 StringUtils.hasText(id)
103                 content != null
104             }
105         and: 'correct content'
106             with(cpsDataUpdatedEvent.content) {
107                 assert isExpectedDateTimeFormat(observedTimestamp): "$observedTimestamp is not in $dateTimeFormat format"
108                 assert observedTimestamp == deletionTimestamp
109                 assert anchorName == 'my-anchorname'
110                 assert dataspaceName == 'my-dataspace'
111                 assert schemaSetName == 'my-schemaset-name'
112                 assert operation == Content.Operation.DELETE
113                 assert data == null
114             }
115     }
116
117     def 'Create CPS Data Event with URI Syntax Exception'() {
118         given: 'an anchor'
119             def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
120         and: 'a mocked data Node (collection)'
121             def mockDataNode = Mock(DataNode)
122             mockCpsDataService.getDataNodes(*_) >> [ mockDataNode ]
123         and: 'a URI syntax exception is thrown somewhere (using datanode as cannot manipulate hardcoded URIs'
124             def originalException = new URISyntaxException('input', 'reason', 0)
125             mockDataNode.getXpath() >> { throw originalException }
126         when: 'attempt to create data updated event'
127             objectUnderTest.createCpsDataUpdatedEvent(anchor, OffsetDateTime.now(), Operation.UPDATE)
128         then: 'the same exception is thrown up'
129             def thrownUp = thrown(URISyntaxException)
130             assert thrownUp == originalException
131     }
132
133     def isExpectedDateTimeFormat(String observedTimestamp) {
134         try {
135             DateTimeFormatter.ofPattern(dateTimeFormat).parse(observedTimestamp)
136         } catch (DateTimeParseException) {
137             return false
138         }
139         return true
140     }
141
142 }