Repository: cloudstack Updated Branches: refs/heads/master 370554e9d -> ea0dec77d
Refactor DbUpgradeUtils - Move database access code to new class DatabaseAccessObject. This was done to ease the effort of testing, since DbUpgradeUtils has a static API and it is harder to mock static things with Mockito. - Log exceptions even if ignored - Add unit tests for both DbUpgradeUtils and DatabaseAccessObject - DbUpgradeUtils.dropTableColumnsIfExist(...) no longer throws CloudRuntimeException to make it consistent with the other methods in the class Signed-off-by: Daan Hoogland <d...@onecht.net> Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ea0dec77 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ea0dec77 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ea0dec77 Branch: refs/heads/master Commit: ea0dec77d98e14e47ca715c46cd0316faa37844c Parents: 370554e Author: miguelaferreira <mferre...@shubergphilis.com> Authored: Tue Mar 4 16:41:20 2014 +0100 Committer: Daan Hoogland <d...@onecht.net> Committed: Thu Mar 6 14:48:35 2014 +0100 ---------------------------------------------------------------------- .../cloud/upgrade/dao/DatabaseAccessObject.java | 99 ++++ .../com/cloud/upgrade/dao/DbUpgradeUtils.java | 76 +-- .../upgrade/dao/DatabaseAccessObjectTest.java | 463 +++++++++++++++++++ .../cloud/upgrade/dao/DbUpgradeUtilsTest.java | 162 +++++++ 4 files changed, 732 insertions(+), 68 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ea0dec77/engine/schema/src/com/cloud/upgrade/dao/DatabaseAccessObject.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/upgrade/dao/DatabaseAccessObject.java b/engine/schema/src/com/cloud/upgrade/dao/DatabaseAccessObject.java new file mode 100644 index 0000000..836a537 --- /dev/null +++ b/engine/schema/src/com/cloud/upgrade/dao/DatabaseAccessObject.java @@ -0,0 +1,99 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.upgrade.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.apache.log4j.Logger; + +public class DatabaseAccessObject { + + private static Logger s_logger = Logger.getLogger(DatabaseAccessObject.class); + + public void dropKey(Connection conn, String tableName, String key, boolean isForeignKey) { + PreparedStatement pstmt = null; + try { + if (isForeignKey) { + pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP FOREIGN KEY " + key); + } else { + pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP KEY " + key); + } + pstmt.executeUpdate(); + s_logger.debug("Key " + key + " is dropped successfully from the table " + tableName); + } catch (SQLException e) { + s_logger.warn("Ignored SQL Exception when trying to drop " + (isForeignKey ? "foreign " : "") + "key " + key + " on table " + tableName, e); + } finally { + closePreparedStatement(pstmt, "Ignored SQL Exception when trying to close PreparedStatement atfer dropping " + (isForeignKey ? "foreign " : "") + "key " + key + + " on table " + tableName); + } + } + + public void dropPrimaryKey(Connection conn, String tableName) { + PreparedStatement pstmt = null; + try { + pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP PRIMARY KEY "); + pstmt.executeUpdate(); + s_logger.debug("Primary key is dropped successfully from the table " + tableName); + } catch (SQLException e) { + s_logger.warn("Ignored SQL Exception when trying to drop primary key on table " + tableName, e); + } finally { + closePreparedStatement(pstmt, "Ignored SQL Exception when trying to close PreparedStatement atfer dropping primary key on table " + tableName); + } + } + + public void dropColumn(Connection conn, String tableName, String columnName) { + PreparedStatement pstmt = null; + try { + pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP COLUMN " + columnName); + pstmt.executeUpdate(); + s_logger.debug("Column " + columnName + " is dropped successfully from the table " + tableName); + } catch (SQLException e) { + s_logger.warn("Unable to drop columns using query " + pstmt + " due to exception", e); + } finally { + closePreparedStatement(pstmt, "Ignored SQL Exception when trying to close PreparedStatement after dropping column " + columnName + " on table " + tableName); + } + } + + public boolean columnExists(Connection conn, String tableName, String columnName) { + boolean columnExists = false; + PreparedStatement pstmt = null; + try { + pstmt = conn.prepareStatement("SELECT " + columnName + " FROM " + tableName); + pstmt.executeQuery(); + columnExists = true; + } catch (SQLException e) { + s_logger.warn("Field " + columnName + " doesn't exist in " + tableName, e); + } finally { + closePreparedStatement(pstmt, "Ignored SQL Exception when trying to close PreparedStatement atfer checking if column " + columnName + " existed on table " + tableName); + } + + return columnExists; + } + + protected static void closePreparedStatement(PreparedStatement pstmt, String errorMessage) { + try { + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + s_logger.warn(errorMessage, e); + } + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ea0dec77/engine/schema/src/com/cloud/upgrade/dao/DbUpgradeUtils.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/upgrade/dao/DbUpgradeUtils.java b/engine/schema/src/com/cloud/upgrade/dao/DbUpgradeUtils.java index af23b87..38ca5c9 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/DbUpgradeUtils.java +++ b/engine/schema/src/com/cloud/upgrade/dao/DbUpgradeUtils.java @@ -17,88 +17,28 @@ package com.cloud.upgrade.dao; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; import java.util.List; -import org.apache.log4j.Logger; - -import com.cloud.utils.exception.CloudRuntimeException; - public class DbUpgradeUtils { - final static Logger s_logger = Logger.getLogger(DbUpgradeUtils.class); + + private static DatabaseAccessObject dao = new DatabaseAccessObject(); public static void dropKeysIfExist(Connection conn, String tableName, List<String> keys, boolean isForeignKey) { for (String key : keys) { - PreparedStatement pstmt = null; - try { - if (isForeignKey) { - pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP FOREIGN KEY " + key); - } else { - pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP KEY " + key); - } - pstmt.executeUpdate(); - s_logger.debug("Key " + key + " is dropped successfully from the table " + tableName); - } catch (SQLException e) { - // do nothing here - - continue; - } finally { - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } + dao.dropKey(conn, tableName, key, isForeignKey); } } public static void dropPrimaryKeyIfExists(Connection conn, String tableName) { - PreparedStatement pstmt = null; - try { - pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP PRIMARY KEY "); - pstmt.executeUpdate(); - s_logger.debug("Primary key is dropped successfully from the table " + tableName); - } catch (SQLException e) { - // do nothing here - } finally { - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } + dao.dropPrimaryKey(conn, tableName); } public static void dropTableColumnsIfExist(Connection conn, String tableName, List<String> columns) { - PreparedStatement pstmt = null; - try { - for (String column : columns) { - try { - pstmt = conn.prepareStatement("SELECT " + column + " FROM " + tableName); - pstmt.executeQuery(); - } catch (SQLException e) { - // if there is an exception, it means that field doesn't exist, so do nothing here - s_logger.trace("Field " + column + " doesn't exist in " + tableName); - continue; - } - - pstmt = conn.prepareStatement("ALTER TABLE " + tableName + " DROP COLUMN " + column); - pstmt.executeUpdate(); - s_logger.debug("Column " + column + " is dropped successfully from the table " + tableName); - } - } catch (SQLException e) { - s_logger.warn("Unable to drop columns using query " + pstmt + " due to exception", e); - throw new CloudRuntimeException("Unable to drop columns due to ", e); - } finally { - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { + for (String columnName : columns) { + if (dao.columnExists(conn, tableName, columnName)) { + dao.dropColumn(conn, tableName, columnName); } } } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ea0dec77/engine/schema/test/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java ---------------------------------------------------------------------- diff --git a/engine/schema/test/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java b/engine/schema/test/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java new file mode 100644 index 0000000..5d37fbf --- /dev/null +++ b/engine/schema/test/com/cloud/upgrade/dao/DatabaseAccessObjectTest.java @@ -0,0 +1,463 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.upgrade.dao; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.apache.log4j.Logger; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.internal.util.reflection.Whitebox; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DatabaseAccessObjectTest { + + @Mock + private PreparedStatement preparedStatementMock; + + @Mock + private Connection connectionMock; + + @Mock + private Logger loggerMock; + + private final DatabaseAccessObject dao = new DatabaseAccessObject(); + + @Before + public void setup() { + Whitebox.setInternalState(dao, "s_logger", loggerMock); + } + + @Test + public void testDropKey() throws Exception { + when(connectionMock.prepareStatement(contains("DROP KEY"))).thenReturn(preparedStatementMock); + + Connection conn = connectionMock; + String tableName = "tableName"; + String key = "key"; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).debug(anyString()); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @Test(expected = NullPointerException.class) + public void testDropKeyWhenConnectionIsNull() throws Exception { + Connection conn = null; + String tableName = "tableName"; + String key = "key"; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + } + + @Test + public void testDropKeyWhenTableNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("null DROP KEY"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + String key = "key"; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropKeyWhenKeyIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("DROP KEY null"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String key = null; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropKeyWhenKeysAreForeignKeys() throws Exception { + when(connectionMock.prepareStatement(contains("DROP FOREIGN KEY"))).thenReturn(preparedStatementMock); + + Connection conn = connectionMock; + String tableName = "tableName"; + String key = "key"; + boolean isForeignKey = true; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).debug(anyString()); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @Test + public void testDropKeyWhenPrepareStatementResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(any(String.class))).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String key = "key"; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(0)).executeUpdate(); + verify(preparedStatementMock, times(0)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropKeyWhenExecuteUpdateResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("DROP KEY"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String key = "key"; + boolean isForeignKey = false; + + dao.dropKey(conn, tableName, key, isForeignKey); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @SuppressWarnings("static-access") + @Test + public void testClosePreparedStatementWhenPreparedStatementIsNull() throws Exception { + PreparedStatement preparedStatement = null; + String errorMessage = "some message"; + + dao.closePreparedStatement(preparedStatement, errorMessage); + + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @SuppressWarnings("static-access") + @Test + public void testClosePreparedStatementWhenPreparedStatementIsNotNullAndThereIsNoException() throws Exception { + PreparedStatement preparedStatement = preparedStatementMock; + String errorMessage = "some message"; + + dao.closePreparedStatement(preparedStatement, errorMessage); + + verify(preparedStatement, times(1)).close(); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @SuppressWarnings("static-access") + @Test + public void testClosePreparedStatementWhenPreparedStatementIsNotNullAndThereIsException() throws Exception { + SQLException sqlException = new SQLException(); + doThrow(sqlException).when(preparedStatementMock).close(); + + PreparedStatement preparedStatement = preparedStatementMock; + String errorMessage = "some message"; + + dao.closePreparedStatement(preparedStatement, errorMessage); + + verify(preparedStatement, times(1)).close(); + verify(loggerMock, times(1)).warn(errorMessage, sqlException); + } + + @Test + public void testDropPrimaryKey() throws Exception { + when(connectionMock.prepareStatement(contains("DROP PRIMARY KEY"))).thenReturn(preparedStatementMock); + + Connection conn = connectionMock; + String tableName = "tableName"; + + dao.dropPrimaryKey(conn, tableName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).debug(anyString()); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @Test(expected = NullPointerException.class) + public void testDropPrimaryKeyWhenConnectionIsNull() throws Exception { + Connection conn = null; + String tableName = "tableName"; + + dao.dropPrimaryKey(conn, tableName); + } + + @Test + public void testDropPrimaryKeyWhenTableNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("null DROP PRIMARY KEY"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + + dao.dropPrimaryKey(conn, tableName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropPrimaryKeyWhenPrepareStatementResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("DROP PRIMARY KEY"))).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + + dao.dropPrimaryKey(conn, tableName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(0)).executeUpdate(); + verify(preparedStatementMock, times(0)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropPrimaryKeyWhenExecuteUpdateResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("DROP PRIMARY KEY"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + + dao.dropPrimaryKey(conn, tableName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testColumnExists() throws Exception { + when(connectionMock.prepareStatement(contains("SELECT"))).thenReturn(preparedStatementMock); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.columnExists(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeQuery(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @Test(expected = NullPointerException.class) + public void testColumnExistsWhenConnectionIsNull() throws Exception { + Connection conn = null; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.columnExists(conn, tableName, columnName); + } + + @Test + public void testColumnExistsWhenTableNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("FROM null"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeQuery()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + String columnName = "columnName"; + + dao.columnExists(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeQuery(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testColumnExistsWhenColumnNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("SELECT null"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeQuery()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = null; + + dao.columnExists(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeQuery(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropColumn() throws Exception { + when(connectionMock.prepareStatement(anyString())).thenReturn(preparedStatementMock); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.dropColumn(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(0)).executeQuery(); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(1)).debug(anyString()); + verify(loggerMock, times(0)).warn(anyString(), any(Throwable.class)); + } + + @Test(expected = NullPointerException.class) + public void testDropColumnWhenConnectionIsNull() throws Exception { + + Connection conn = null; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.dropColumn(conn, tableName, columnName); + } + + @Test + public void testDropColumnWhenTableNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("ALTER TABLE null"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = null; + String columnName = "columnName"; + + dao.dropColumn(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropColumnWhenColumnNameIsNull() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(contains("DROP COLUMN null"))).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = null; + + dao.dropColumn(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropColumnWhenPrepareStatementResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(anyString())).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.dropColumn(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(0)).executeUpdate(); + verify(preparedStatementMock, times(0)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + + @Test + public void testDropColumnWhenexecuteUpdateResultsInException() throws Exception { + SQLException sqlException = new SQLException(); + when(connectionMock.prepareStatement(anyString())).thenReturn(preparedStatementMock); + when(preparedStatementMock.executeUpdate()).thenThrow(sqlException); + + Connection conn = connectionMock; + String tableName = "tableName"; + String columnName = "columnName"; + + dao.dropColumn(conn, tableName, columnName); + + verify(connectionMock, times(1)).prepareStatement(anyString()); + verify(preparedStatementMock, times(1)).executeUpdate(); + verify(preparedStatementMock, times(1)).close(); + verify(loggerMock, times(0)).debug(anyString()); + verify(loggerMock, times(1)).warn(anyString(), eq(sqlException)); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ea0dec77/engine/schema/test/com/cloud/upgrade/dao/DbUpgradeUtilsTest.java ---------------------------------------------------------------------- diff --git a/engine/schema/test/com/cloud/upgrade/dao/DbUpgradeUtilsTest.java b/engine/schema/test/com/cloud/upgrade/dao/DbUpgradeUtilsTest.java new file mode 100644 index 0000000..d248cfb --- /dev/null +++ b/engine/schema/test/com/cloud/upgrade/dao/DbUpgradeUtilsTest.java @@ -0,0 +1,162 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +package com.cloud.upgrade.dao; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +@RunWith(PowerMockRunner.class) +public class DbUpgradeUtilsTest { + + @Mock + private Connection connectionMock; + + @Mock + private DatabaseAccessObject daoMock; + + @Before + public void setupClass() { + Whitebox.setInternalState(DbUpgradeUtils.class, "dao", daoMock); + } + + @Test + public void testDropKeyIfExistWhenNoKeysAreSupplied() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + List<String> keys = new ArrayList<String>(); + boolean isForeignKey = false; + + DbUpgradeUtils.dropKeysIfExist(conn, tableName, keys, isForeignKey); + + verify(daoMock, times(0)).dropKey(eq(conn), eq(tableName), anyString(), eq(isForeignKey)); + } + + @Test + public void testDropKeyIfExistWhenOneKeysIsSupplied() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + String key = "key"; + List<String> keys = Arrays.asList(new String[] {key}); + boolean isForeignKey = false; + + DbUpgradeUtils.dropKeysIfExist(conn, tableName, keys, isForeignKey); + + verify(daoMock, times(1)).dropKey(conn, tableName, key, isForeignKey); + } + + @Test + public void testDropKeyIfExistWhenThreeKeysAreSupplied() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + String key1 = "key1"; + String key2 = "key2"; + List<String> keys = Arrays.asList(new String[] {key1, key2}); + boolean isForeignKey = false; + + DbUpgradeUtils.dropKeysIfExist(conn, tableName, keys, isForeignKey); + + verify(daoMock, times(1)).dropKey(conn, tableName, key1, isForeignKey); + verify(daoMock, times(1)).dropKey(conn, tableName, key2, isForeignKey); + } + + @Test + public void testDropPrimaryKey() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + + DbUpgradeUtils.dropPrimaryKeyIfExists(conn, tableName); + + verify(daoMock, times(1)).dropPrimaryKey(conn, tableName); + } + + @Test + public void testDropTableColumnsIfExistWhenNoKeysAreSupplied() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + List<String> columns = new ArrayList<String>(); + + DbUpgradeUtils.dropTableColumnsIfExist(conn, tableName, columns); + + verify(daoMock, times(0)).columnExists(eq(conn), eq(tableName), anyString()); + verify(daoMock, times(0)).dropColumn(eq(conn), eq(tableName), anyString()); + } + + @Test + public void testDropTableColumnsIfExistWhenOneKeysIsSuppliedAndColumnExists() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + String column = "column"; + when(daoMock.columnExists(conn, tableName, column)).thenReturn(true); + List<String> columns = Arrays.asList(new String[] {column}); + + DbUpgradeUtils.dropTableColumnsIfExist(conn, tableName, columns); + + verify(daoMock, times(1)).columnExists(conn, tableName, column); + verify(daoMock, times(1)).dropColumn(conn, tableName, column); + } + + @Test + public void testDropTableColumnsIfExistWhenOneKeysIsSuppliedAndColumnDoesNotExists() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + String column = "column"; + when(daoMock.columnExists(conn, tableName, column)).thenReturn(false); + List<String> columns = Arrays.asList(new String[] {column}); + + DbUpgradeUtils.dropTableColumnsIfExist(conn, tableName, columns); + + verify(daoMock, times(1)).columnExists(conn, tableName, column); + verify(daoMock, times(0)).dropColumn(conn, tableName, column); + } + + @Test + public void testDropTableColumnsIfExistWhenThreeKeysAreSuppliedAnOneDoesnotExist() throws Exception { + Connection conn = connectionMock; + String tableName = "tableName"; + String column1 = "column1"; + String column2 = "column2"; + String column3 = "column3"; + when(daoMock.columnExists(conn, tableName, column1)).thenReturn(true); + when(daoMock.columnExists(conn, tableName, column2)).thenReturn(false); + when(daoMock.columnExists(conn, tableName, column3)).thenReturn(true); + List<String> keys = Arrays.asList(new String[] {column1, column2, column3}); + + DbUpgradeUtils.dropTableColumnsIfExist(conn, tableName, keys); + + verify(daoMock, times(1)).columnExists(conn, tableName, column1); + verify(daoMock, times(1)).dropColumn(conn, tableName, column1); + verify(daoMock, times(1)).columnExists(conn, tableName, column2); + verify(daoMock, times(0)).dropColumn(conn, tableName, column2); + verify(daoMock, times(1)).columnExists(conn, tableName, column3); + verify(daoMock, times(1)).dropColumn(conn, tableName, column3); + } +}