diff options
2 files changed, 252 insertions, 11 deletions
diff --git a/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/main/java/org/onap/appc/lockmanager/impl/sql/pessimistic/SqlLockManager.java b/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/main/java/org/onap/appc/lockmanager/impl/sql/pessimistic/SqlLockManager.java index ab3db91ee..59e84eb1d 100644 --- a/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/main/java/org/onap/appc/lockmanager/impl/sql/pessimistic/SqlLockManager.java +++ b/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/main/java/org/onap/appc/lockmanager/impl/sql/pessimistic/SqlLockManager.java @@ -5,6 +5,8 @@ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson * ============================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,10 +37,10 @@ import org.onap.appc.lockmanager.impl.sql.Messages; abstract class SqlLockManager extends JdbcLockManager { - private static final String SQL_LOAD_LOCK_RECORD = "SELECT * FROM %s WHERE RESOURCE_ID=?"; - private static final String SQL_INSERT_LOCK_RECORD = "INSERT INTO %s (RESOURCE_ID, OWNER_ID, UPDATED, TIMEOUT) VALUES (?, ?, ?, ?)"; - private static final String SQL_UPDATE_LOCK_RECORD = "UPDATE %s SET OWNER_ID=?, UPDATED=?, TIMEOUT=? WHERE RESOURCE_ID=?"; - private static final String SQL_CURRENT_TIMESTAMP = "SELECT CURRENT_TIMESTAMP()"; + static final String SQL_LOAD_LOCK_RECORD = "SELECT * FROM %s WHERE RESOURCE_ID=?"; + static final String SQL_INSERT_LOCK_RECORD = "INSERT INTO %s (RESOURCE_ID, OWNER_ID, UPDATED, TIMEOUT) VALUES (?, ?, ?, ?)"; + static final String SQL_UPDATE_LOCK_RECORD = "UPDATE %s SET OWNER_ID=?, UPDATED=?, TIMEOUT=? WHERE RESOURCE_ID=?"; + static final String SQL_CURRENT_TIMESTAMP = "SELECT CURRENT_TIMESTAMP()"; private String sqlLoadLockRecord; private String sqlInsertLockRecord; @@ -86,13 +88,13 @@ abstract class SqlLockManager extends JdbcLockManager { @Override public boolean isLocked(String resource) { - Connection connection=openDbConnection(); + Connection connection = openDbConnection(); try { - LockRecord lockRecord=loadLockRecord(connection,resource); - if(lockRecord==null){ + LockRecord lockRecord = loadLockRecord(connection,resource); + if(lockRecord == null){ return false; }else{ - if(lockRecord.getOwner()==null){ + if(lockRecord.getOwner() == null){ return false; }else if(isLockExpired(lockRecord, connection)){ return false; @@ -112,7 +114,7 @@ abstract class SqlLockManager extends JdbcLockManager { Connection connection=openDbConnection(); try { org.onap.appc.lockmanager.impl.sql.pessimistic.LockRecord lockRecord=loadLockRecord(connection,resource); - if(lockRecord==null || lockRecord.getOwner() ==null ){ + if(lockRecord == null || lockRecord.getOwner() == null ){ return null; }else{ if(isLockExpired(lockRecord, connection)){ diff --git a/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/test/java/org/onap/appc/lockmanager/impl/sql/pessimistic/TestMySqlLockManager.java b/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/test/java/org/onap/appc/lockmanager/impl/sql/pessimistic/TestMySqlLockManager.java index 6e818cfed..63eb54c79 100644 --- a/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/test/java/org/onap/appc/lockmanager/impl/sql/pessimistic/TestMySqlLockManager.java +++ b/appc-dispatcher/appc-dispatcher-common/lock-manager-lib/lock-manager-impl/src/test/java/org/onap/appc/lockmanager/impl/sql/pessimistic/TestMySqlLockManager.java @@ -5,6 +5,8 @@ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson * ============================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,16 +25,35 @@ package org.onap.appc.lockmanager.impl.sql.pessimistic; +import static org.hamcrest.CoreMatchers.isA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.onap.appc.dao.util.api.JdbcConnectionFactory; import org.onap.appc.lockmanager.api.LockException; import org.onap.appc.lockmanager.api.LockRuntimeException; import org.onap.appc.lockmanager.impl.sql.JdbcLockManager; import org.onap.appc.lockmanager.impl.sql.MySqlLockManagerBaseTests; import org.onap.appc.lockmanager.impl.sql.Synchronizer; -import org.onap.appc.lockmanager.impl.sql.pessimistic.MySqlLockManager; -import java.util.concurrent.*; public class TestMySqlLockManager extends MySqlLockManagerBaseTests { @@ -120,4 +141,222 @@ public class TestMySqlLockManager extends MySqlLockManagerBaseTests { setSynchronizer(null); } } + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public void testAcquireLockNullOwner() throws LockException { + MySqlLockManager lockManager = new MySqlLockManager(); + expectedEx.expect(LockRuntimeException.class); + lockManager.acquireLock(null, null, 0); + } + + @Test + public void testIsLocked() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Mockito.doThrow(new SQLException()).when(lockManager).loadLockRecord(Mockito.any(Connection.class), Mockito.anyString()); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(Mockito.mock(Connection.class)); + lockManager.setConnectionFactory(connectionFactory); + expectedEx.expect(LockRuntimeException.class); + lockManager.isLocked(" "); + } + + @Test + public void testGetLockOwnerExceptionFlow() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Mockito.doThrow(new SQLException()).when(lockManager).loadLockRecord(Mockito.any(Connection.class), Mockito.anyString()); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(Mockito.mock(Connection.class)); + lockManager.setConnectionFactory(connectionFactory); + expectedEx.expect(LockRuntimeException.class); + lockManager.getLockOwner(" "); + } + + @Test + public void testGetLockOwnerNull() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Mockito.doReturn(null).when(lockManager).loadLockRecord(Mockito.any(Connection.class), Mockito.anyString()); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(Mockito.mock(Connection.class)); + lockManager.setConnectionFactory(connectionFactory); + assertNull(lockManager.getLockOwner(" ")); + } + + @Test + public void testGetLockOwnerExpired() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + LockRecord lockRecord = Mockito.mock(LockRecord.class); + Mockito.when(lockRecord.getTimeout()).thenReturn(1L); + Mockito.when(lockRecord.getUpdated()).thenReturn(System.currentTimeMillis()-100); + Mockito.when(lockRecord.getOwner()).thenReturn("OWNER"); + Mockito.doReturn(lockRecord).when(lockManager).loadLockRecord(Mockito.any(Connection.class), Mockito.anyString()); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Connection connection = Mockito.mock(Connection.class); + PreparedStatement statement = Mockito.mock(PreparedStatement.class); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(resultSet.getTimestamp(1)).thenReturn(new Timestamp(System.currentTimeMillis())); + Mockito.when(statement.executeQuery()).thenReturn(resultSet); + Mockito.when(connection.prepareStatement(SqlLockManager.SQL_CURRENT_TIMESTAMP)).thenReturn(statement); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(connection); + lockManager.setConnectionFactory(connectionFactory); + assertNull(lockManager.getLockOwner(" ")); + } + + @Test + public void testGetLockOwnerNotExpired() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + LockRecord lockRecord = Mockito.mock(LockRecord.class); + Mockito.when(lockRecord.getTimeout()).thenReturn(1L); + Mockito.when(lockRecord.getUpdated()).thenReturn(System.currentTimeMillis()+10000); + Mockito.when(lockRecord.getOwner()).thenReturn("OWNER"); + Mockito.doReturn(lockRecord).when(lockManager).loadLockRecord(Mockito.any(Connection.class), Mockito.anyString()); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Connection connection = Mockito.mock(Connection.class); + PreparedStatement statement = Mockito.mock(PreparedStatement.class); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(resultSet.getTimestamp(1)).thenReturn(new Timestamp(System.currentTimeMillis())); + Mockito.when(statement.executeQuery()).thenReturn(resultSet); + Mockito.when(connection.prepareStatement(SqlLockManager.SQL_CURRENT_TIMESTAMP)).thenReturn(statement); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(connection); + lockManager.setConnectionFactory(connectionFactory); + assertEquals("OWNER", lockManager.getLockOwner(" ")); + } + + @Test + public void testLoadLockRecord() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + lockManager.setTableName("TABLE_NAME"); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Connection connection = Mockito.mock(Connection.class); + PreparedStatement statement = Mockito.mock(PreparedStatement.class); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(resultSet.getString(2)).thenReturn("OWNER"); + Mockito.when(resultSet.getLong(3)).thenReturn(0L); + Mockito.when(resultSet.getLong(4)).thenReturn(0L); + Mockito.when(resultSet.getLong(5)).thenReturn(0L); + Mockito.when(statement.executeQuery()).thenReturn(resultSet); + Mockito.when(connection.prepareStatement(String.format(SqlLockManager.SQL_LOAD_LOCK_RECORD, "TABLE_NAME"))).thenReturn(statement); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(connection); + lockManager.setConnectionFactory(connectionFactory); + assertTrue(lockManager.loadLockRecord(connection, "") instanceof LockRecord); + } + + @Test + public void testAddLockRecord() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + lockManager.setTableName("TABLE_NAME"); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Connection connection = Mockito.mock(Connection.class); + PreparedStatement statement2 = Mockito.mock(PreparedStatement.class); + ResultSet resultSet2 = Mockito.mock(ResultSet.class); + Mockito.when(resultSet2.next()).thenReturn(true); + Mockito.when(resultSet2.getTimestamp(1)).thenReturn(new Timestamp(System.currentTimeMillis())); + Mockito.when(statement2.executeQuery()).thenReturn(resultSet2); + Mockito.when(connection.prepareStatement(SqlLockManager.SQL_CURRENT_TIMESTAMP)).thenReturn(statement2); + + PreparedStatement statement = Mockito.mock(PreparedStatement.class); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(resultSet.getString(2)).thenReturn("OWNER"); + Mockito.when(resultSet.getLong(3)).thenReturn(0L); + Mockito.when(resultSet.getLong(4)).thenReturn(0L); + Mockito.when(resultSet.getLong(5)).thenReturn(0L); + Mockito.when(statement.executeQuery()).thenReturn(resultSet); + Mockito.when(connection.prepareStatement(String.format(SqlLockManager.SQL_INSERT_LOCK_RECORD, "TABLE_NAME"))).thenReturn(statement); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(connection); + lockManager.setConnectionFactory(connectionFactory); + lockManager.addLockRecord(connection, "", "", 0L); + Mockito.verify(statement).executeUpdate(); + } + + @Test + public void testUpdateLockRecord() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + lockManager.setTableName("TABLE_NAME"); + JdbcConnectionFactory connectionFactory = Mockito.mock(JdbcConnectionFactory.class); + Connection connection = Mockito.mock(Connection.class); + PreparedStatement statement2 = Mockito.mock(PreparedStatement.class); + ResultSet resultSet2 = Mockito.mock(ResultSet.class); + Mockito.when(resultSet2.next()).thenReturn(true); + Mockito.when(resultSet2.getTimestamp(1)).thenReturn(new Timestamp(-1)); + Mockito.when(statement2.executeQuery()).thenReturn(resultSet2); + Mockito.when(connection.prepareStatement(SqlLockManager.SQL_CURRENT_TIMESTAMP)).thenReturn(statement2); + + PreparedStatement statement = Mockito.mock(PreparedStatement.class); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(resultSet.getString(2)).thenReturn("OWNER"); + Mockito.when(resultSet.getLong(3)).thenReturn(0L); + Mockito.when(resultSet.getLong(4)).thenReturn(0L); + Mockito.when(resultSet.getLong(5)).thenReturn(0L); + Mockito.when(statement.executeQuery()).thenReturn(resultSet); + Mockito.when(connection.prepareStatement(String.format(SqlLockManager.SQL_UPDATE_LOCK_RECORD, "TABLE_NAME"))).thenReturn(statement); + Mockito.when(connectionFactory.openDbConnection()).thenReturn(connection); + lockManager.setConnectionFactory(connectionFactory); + lockManager.updateLockRecord(connection, "", "", 0L); + Mockito.verify(statement).executeUpdate(); + } + + @Test + public void testEnterCriticalSectionLockRuntimeException() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Connection connection = Mockito.mock(Connection.class); + CallableStatement callableStatement = Mockito.mock(CallableStatement.class); + Mockito.when(connection.prepareCall("SELECT COALESCE(GET_LOCK(?,?),0)")).thenReturn(callableStatement); + expectedEx.expect(LockRuntimeException.class); + expectedEx.expectMessage("Cannot obtain critical section lock for resource [null]."); + lockManager.enterCriticalSection(connection, null); + } + + @Test + public void testEnterCriticalSectionLockRuntimeException2() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Connection connection = Mockito.mock(Connection.class); + Mockito.when(connection.prepareCall("SELECT COALESCE(GET_LOCK(?,?),0)")).thenThrow(new SQLException()); + expectedEx.expect(LockRuntimeException.class); + expectedEx.expectMessage("Cannot obtain critical section lock for resource [null]."); + expectedEx.expectCause(isA(SQLException.class)); + lockManager.enterCriticalSection(connection, null); + } + + @Test + public void testEnterCriticalSection() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Connection connection = Mockito.mock(Connection.class); + CallableStatement callableStatement = Mockito.mock(CallableStatement.class); + Mockito.when(callableStatement.execute()).thenReturn(true); + ResultSet resultSet = Mockito.mock(ResultSet.class); + Mockito.when(resultSet.getInt(1)).thenReturn(1); + Mockito.when(resultSet.next()).thenReturn(true); + Mockito.when(callableStatement.getResultSet()).thenReturn(resultSet); + Mockito.when(connection.prepareCall("SELECT COALESCE(GET_LOCK(?,?),0)")).thenReturn(callableStatement); + lockManager.enterCriticalSection(connection, null); + Mockito.verify(callableStatement).close(); + } + + @Test + public void testLeaveCriticalSection() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Connection connection = Mockito.mock(Connection.class); + CallableStatement callableStatement = Mockito.mock(CallableStatement.class); + Mockito.when(connection.prepareCall("SELECT RELEASE_LOCK(?)")).thenReturn(callableStatement); + lockManager.leaveCriticalSection(connection, null); + Mockito.verify(callableStatement).close(); + } + + @Test + public void testLeaveCriticalSectionExceptionFlow() throws SQLException { + MySqlLockManager lockManager = Mockito.spy(new MySqlLockManager()); + Connection connection = Mockito.mock(Connection.class); + Mockito.when(connection.prepareCall("SELECT RELEASE_LOCK(?)")).thenThrow(new SQLException()); + expectedEx.expect(LockRuntimeException.class); + lockManager.leaveCriticalSection(connection, null); + expectedEx.expectMessage("Error releasing critical section lock."); + expectedEx.expectCause(isA(SQLException.class)); + } } |