summaryrefslogtreecommitdiffstats
path: root/cps-ri/src/test/groovy/org/onap/cps/spi/utils/SessionManagerSpec.groovy
blob: db766cd1f34f92997da9e08347ed60cef648f10d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 *  ============LICENSE_START=======================================================
 *  Copyright (C) 2022 Nordix Foundation
 *  ================================================================================
 *  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.spi.utils

import com.google.common.util.concurrent.TimeLimiter
import org.hibernate.HibernateException
import org.hibernate.Transaction
import org.onap.cps.spi.config.CpsSessionFactory
import org.onap.cps.spi.entities.AnchorEntity
import org.onap.cps.spi.exceptions.SessionManagerException
import org.onap.cps.spi.repository.AnchorRepository
import org.onap.cps.spi.repository.DataspaceRepository
import spock.lang.Specification
import org.hibernate.Session
import java.util.concurrent.ExecutionException

class SessionManagerSpec extends Specification {

    def mockCpsSessionFactory = Mock(CpsSessionFactory)
    def spiedTimeLimiterProvider = Spy(TimeLimiterProvider)
    def mockDataspaceRepository = Mock(DataspaceRepository)
    def mockAnchorRepository = Mock(AnchorRepository)
    def mockSession1 = Mock(Session)
    def mockSession2 = Mock(Session)
    def mockTransaction1 = Mock(Transaction)
    def mockTransaction2 = Mock(Transaction)

    def objectUnderTest = new SessionManager(mockCpsSessionFactory, spiedTimeLimiterProvider, mockDataspaceRepository, mockAnchorRepository)

    def setup(){
        mockSession1.getTransaction() >> mockTransaction1
        mockSession2.getTransaction() >> mockTransaction2
    }

    def 'Lock anchor entity with #exceptionDuringTest exception.'() {
        given: 'a dummy session'
            objectUnderTest.sessionMap.put('dummy-session', mockSession1)
        and: 'the anchor name can be resolved'
            def mockAnchorEntity = Mock(AnchorEntity)
            mockAnchorEntity.getId() > 456
            mockAnchorRepository.getByDataspaceAndName(_, _) >> mockAnchorEntity
        and: 'timeLimiter throws an #exceptionDuringTest exception'
            def mockTimeLimiter = Mock(TimeLimiter)
            spiedTimeLimiterProvider.getTimeLimiter(_) >> mockTimeLimiter
            mockTimeLimiter.callWithTimeout(*_) >> { throw exceptionDuringTest }
        when: 'session tries to acquire anchor lock'
            objectUnderTest.lockAnchor('dummy-session', 'some-dataspace', 'some-anchor', 123L)
        then: 'a session manager exception is thrown with the expected detail'
            def thrown = thrown(SessionManagerException)
            thrown.details.contains(expectedExceptionDetail)
        where:
            exceptionDuringTest        || expectedExceptionDetail
            new InterruptedException() || 'interrupted'
            new ExecutionException()   || 'aborted'
    }

    def 'Close a session' () {
        given: 'a session in the session map'
            objectUnderTest.sessionMap.putAll([testSessionId1:mockSession1])
        when: 'the session manager closes session'
            objectUnderTest.closeSession('testSessionId1', commit)
        then: 'commit or rollback is called on the transaction as appropriate'
            if (commit) {
                1 * mockTransaction1.commit()
            } else {
                1 * mockTransaction1.rollback()
            }
        and: 'the correct session is closed'
            1 * mockSession1.close()
        where:
            commit << [SessionManager.WITH_COMMIT, SessionManager.WITH_ROLLBACK]
    }

    def 'Close session that does not exist.'() {
        when: 'attempt to close session that does not exist'
            objectUnderTest.closeSession('unknown session id', SessionManager.WITH_COMMIT)
        then: 'a session manager exception is thrown with the unknown id in the details'
            def thrown = thrown(SessionManagerException)
            assert thrown.details.contains('unknown session id')
    }

    def 'Hibernate exception while closing session.'() {
        given: 'a test session in session map'
            objectUnderTest.sessionMap.put('testSessionId', mockSession1)
        and: 'an hibernate exception when closing that session'
            def hibernateException = new HibernateException('test')
            mockSession1.close() >> { throw hibernateException }
        when: 'attempt to close session'
            objectUnderTest.closeSession('testSessionId', SessionManager.WITH_COMMIT)
        then: 'a session manager exception is thrown with the session id in the details'
            def thrown = thrown(SessionManagerException)
            assert thrown.details.contains('testSessionId')
        and: 'the original exception as cause'
            assert thrown.cause == hibernateException
    }

    def 'Attempt to lock anchor entity with session Id that does not exist'() {
        when: 'attempt to acquire anchor lock with session that does not exist'
            objectUnderTest.lockAnchor('unknown session id', '', '', 123L)
        then: 'a session manager exception is thrown with the unknown id in the details'
            def thrown = thrown(SessionManagerException)
            thrown.details.contains('unknown session id')
    }

    def 'Close all sessions in shutdown.'() {
        given: 'sessions that holds transactions in the session map'
            objectUnderTest.sessionMap.putAll([testSessionId1:mockSession1, otherSessionId:mockSession2])
        when: 'shutdown method to close all sessions is called'
            objectUnderTest.closeAllSessionsInShutdown()
        then: 'commit is called on each transaction'
            1 * mockTransaction1.rollback()
            1 * mockTransaction2.rollback()
        and: 'each session is closed'
            1 * mockSession1.close()
            1 * mockSession2.close()
        then: 'session factory is closed'
            1 * mockCpsSessionFactory.closeSessionFactory()
    }

}