Add graceful shutdown for Session Manager
[cps.git] / cps-ri / src / test / groovy / org / onap / cps / spi / utils / SessionManagerSpec.groovy
index a2df06e..db766cd 100644 (file)
@@ -23,28 +23,36 @@ 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 org.testcontainers.shaded.com.google.common.util.concurrent.UncheckedExecutionException
 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 mockSession = Mock(Session)
+    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 objectUnderTest = new SessionManager(spiedTimeLimiterProvider, mockDataspaceRepository, mockAnchorRepository)
+    def setup(){
+        mockSession1.getTransaction() >> mockTransaction1
+        mockSession2.getTransaction() >> mockTransaction2
+    }
 
-    def 'Lock anchor entity with #exceptionDuringTest exception.'(){
+    def 'Lock anchor entity with #exceptionDuringTest exception.'() {
         given: 'a dummy session'
-            objectUnderTest.sessionMap.put('dummySession', mockSession)
+            objectUnderTest.sessionMap.put('dummy-session', mockSession1)
         and: 'the anchor name can be resolved'
             def mockAnchorEntity = Mock(AnchorEntity)
             mockAnchorEntity.getId() > 456
@@ -54,33 +62,49 @@ class SessionManagerSpec extends Specification {
             spiedTimeLimiterProvider.getTimeLimiter(_) >> mockTimeLimiter
             mockTimeLimiter.callWithTimeout(*_) >> { throw exceptionDuringTest }
         when: 'session tries to acquire anchor lock'
-            objectUnderTest.lockAnchor('dummySession', 'some-dataspace','some-anchor', 123L)
+            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'
+            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')
+            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 with a transaction'
-            objectUnderTest.sessionMap.put('testSessionId', mockSession)
-            mockSession.getTransaction() >> Mock(Transaction)
+        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')
-            mockSession.close() >> { throw hibernateException }
+            mockSession1.close() >> { throw hibernateException }
         when: 'attempt to close session'
-            objectUnderTest.closeSession('testSessionId')
+            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')
@@ -88,12 +112,27 @@ class SessionManagerSpec extends Specification {
             assert thrown.cause == hibernateException
     }
 
-    def 'Attempt to lock anchor entity with session Id that does not exists'(){
-        when: 'attempt to acquire anchor lock with session that does not exists'
-            objectUnderTest.lockAnchor('unknown session id','','',123L)
+    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()
+    }
+
 }