You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ml...@apache.org on 2014/03/08 01:23:03 UTC

[30/50] [abbrv] git commit: updated refs/heads/resize-root to 0eb9967

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 <da...@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/resize-root
Commit: ea0dec77d98e14e47ca715c46cd0316faa37844c
Parents: 370554e
Author: miguelaferreira <mf...@shubergphilis.com>
Authored: Tue Mar 4 16:41:20 2014 +0100
Committer: Daan Hoogland <da...@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);
+    }
+}