Merge "CM SUBSCRIPTION: add new subscription for non existing xpath"
[cps.git] / cps-ri / src / test / groovy / org / onap / cps / spi / utils / SessionManagerSpec.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2022 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.spi.utils
22
23 import com.google.common.util.concurrent.TimeLimiter
24 import com.google.common.util.concurrent.UncheckedExecutionException
25 import org.hibernate.HibernateException
26 import org.hibernate.Transaction
27 import org.onap.cps.spi.config.CpsSessionFactory
28 import org.onap.cps.spi.entities.AnchorEntity
29 import org.onap.cps.spi.exceptions.SessionManagerException
30 import org.onap.cps.spi.repository.AnchorRepository
31 import org.onap.cps.spi.repository.DataspaceRepository
32 import spock.lang.Specification
33 import org.hibernate.Session
34 import java.util.concurrent.ExecutionException
35
36 class SessionManagerSpec extends Specification {
37
38     def mockCpsSessionFactory = Mock(CpsSessionFactory)
39     def spiedTimeLimiterProvider = Spy(TimeLimiterProvider)
40     def mockDataspaceRepository = Mock(DataspaceRepository)
41     def mockAnchorRepository = Mock(AnchorRepository)
42     def mockSession1 = Mock(Session)
43     def mockSession2 = Mock(Session)
44     def mockTransaction1 = Mock(Transaction)
45     def mockTransaction2 = Mock(Transaction)
46
47     def objectUnderTest = new SessionManager(mockCpsSessionFactory, spiedTimeLimiterProvider, mockDataspaceRepository, mockAnchorRepository)
48
49     def setup(){
50         mockSession1.getTransaction() >> mockTransaction1
51         mockSession2.getTransaction() >> mockTransaction2
52     }
53
54     def 'Lock anchor entity with #exceptionDuringTest exception.'() {
55         given: 'a dummy session'
56             objectUnderTest.sessionMap.put('dummy-session', mockSession1)
57         and: 'the anchor name can be resolved'
58             def mockAnchorEntity = Mock(AnchorEntity)
59             mockAnchorEntity.getId() > 456
60             mockAnchorRepository.getByDataspaceAndName(_, _) >> mockAnchorEntity
61         and: 'timeLimiter throws an #exceptionDuringTest exception'
62             def mockTimeLimiter = Mock(TimeLimiter)
63             spiedTimeLimiterProvider.getTimeLimiter(_) >> mockTimeLimiter
64             mockTimeLimiter.callWithTimeout(*_) >> { throw exceptionDuringTest }
65         when: 'session tries to acquire anchor lock'
66             objectUnderTest.lockAnchor('dummy-session', 'some-dataspace', 'some-anchor', 123L)
67         then: 'a session manager exception is thrown with the expected detail'
68             def thrown = thrown(SessionManagerException)
69             thrown.details.contains(expectedExceptionDetail)
70         where:
71             exceptionDuringTest               || expectedExceptionDetail
72             new InterruptedException()        || 'interrupted'
73             new UncheckedExecutionException() || 'aborted'
74     }
75
76     def 'Close a session' () {
77         given: 'a session in the session map'
78             objectUnderTest.sessionMap.putAll([testSessionId1:mockSession1])
79         when: 'the session manager closes session'
80             objectUnderTest.closeSession('testSessionId1', commit)
81         then: 'commit or rollback is called on the transaction as appropriate'
82             if (commit) {
83                 1 * mockTransaction1.commit()
84             } else {
85                 1 * mockTransaction1.rollback()
86             }
87         and: 'the correct session is closed'
88             1 * mockSession1.close()
89         where:
90             commit << [SessionManager.WITH_COMMIT, SessionManager.WITH_ROLLBACK]
91     }
92
93     def 'Close session that does not exist.'() {
94         when: 'attempt to close session that does not exist'
95             objectUnderTest.closeSession('unknown session id', SessionManager.WITH_COMMIT)
96         then: 'a session manager exception is thrown with the unknown id in the details'
97             def thrown = thrown(SessionManagerException)
98             assert thrown.details.contains('unknown session id')
99     }
100
101     def 'Hibernate exception while closing session.'() {
102         given: 'a test session in session map'
103             objectUnderTest.sessionMap.put('testSessionId', mockSession1)
104         and: 'an hibernate exception when closing that session'
105             def hibernateException = new HibernateException('test')
106             mockSession1.close() >> { throw hibernateException }
107         when: 'attempt to close session'
108             objectUnderTest.closeSession('testSessionId', SessionManager.WITH_COMMIT)
109         then: 'a session manager exception is thrown with the session id in the details'
110             def thrown = thrown(SessionManagerException)
111             assert thrown.details.contains('testSessionId')
112         and: 'the original exception as cause'
113             assert thrown.cause == hibernateException
114     }
115
116     def 'Attempt to lock anchor entity with session Id that does not exist'() {
117         when: 'attempt to acquire anchor lock with session that does not exist'
118             objectUnderTest.lockAnchor('unknown session id', '', '', 123L)
119         then: 'a session manager exception is thrown with the unknown id in the details'
120             def thrown = thrown(SessionManagerException)
121             thrown.details.contains('unknown session id')
122     }
123
124     def 'Close all sessions in shutdown.'() {
125         given: 'sessions that holds transactions in the session map'
126             objectUnderTest.sessionMap.putAll([testSessionId1:mockSession1, otherSessionId:mockSession2])
127         when: 'shutdown method to close all sessions is called'
128             objectUnderTest.closeAllSessionsInShutdown()
129         then: 'commit is called on each transaction'
130             1 * mockTransaction1.rollback()
131             1 * mockTransaction2.rollback()
132         and: 'each session is closed'
133             1 * mockSession1.close()
134             1 * mockSession2.close()
135         then: 'session factory is closed'
136             1 * mockCpsSessionFactory.closeSessionFactory()
137     }
138
139 }