/** * 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 org.apache.activemq.store.jdbc.adapter; import static org.apache.log4j.Level.DEBUG; import static org.apache.log4j.Level.WARN; import static org.junit.Assert.assertEquals; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.when; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.apache.activemq.store.jdbc.Statements; import org.apache.activemq.store.jdbc.TransactionContext; import org.apache.activemq.util.DefaultTestAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DefaultJDBCAdapterDoCreateTablesTest { private static final String CREATE_STATEMENT1 = "createStatement1"; private static final String CREATE_STATEMENT2 = "createStatement2"; private static final String[] CREATE_STATEMENTS = new String[] { CREATE_STATEMENT1, CREATE_STATEMENT2 }; private static final int VENDOR_CODE = 1; private static final String SQL_STATE = "SqlState"; private static final String MY_REASON = "MyReason"; private DefaultJDBCAdapter defaultJDBCAdapter; private List<LoggingEvent> loggingEvents = new ArrayList<>(); @Mock private TransactionContext transactionContext; @Mock(answer = RETURNS_DEEP_STUBS) private Connection connection; @Mock private Statements statements; @Mock private ResultSet resultSet; @Mock private Statement statement1, statement2; @Before public void setUp() throws IOException, SQLException { DefaultTestAppender appender = new DefaultTestAppender() { @Override public void doAppend(LoggingEvent event) { loggingEvents.add(event); } }; Logger rootLogger = Logger.getRootLogger(); rootLogger.setLevel(Level.DEBUG); rootLogger.addAppender(appender); defaultJDBCAdapter = new DefaultJDBCAdapter(); defaultJDBCAdapter.statements = statements; when(statements.getCreateSchemaStatements()).thenReturn(CREATE_STATEMENTS); when(transactionContext.getConnection()).thenReturn(connection); when(connection.getMetaData().getTables(null, null, this.statements.getFullMessageTableName(),new String[] { "TABLE" })).thenReturn(resultSet); when(connection.createStatement()).thenReturn(statement1, statement2); when(connection.getAutoCommit()).thenReturn(true); } @After public void tearDown() { loggingEvents = new ArrayList<>(); } @Test public void createsTheTablesWhenNoMessageTableExistsAndLogsSqlExceptionsInWarnLevel() throws IOException, SQLException { when(resultSet.next()).thenReturn(false); when(statement2.execute(CREATE_STATEMENT2)).thenThrow(new SQLException(MY_REASON, SQL_STATE, VENDOR_CODE)); defaultJDBCAdapter.doCreateTables(transactionContext); InOrder inOrder = inOrder(resultSet, connection, statement1, statement2); inOrder.verify(resultSet).next(); inOrder.verify(resultSet).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement1).execute(CREATE_STATEMENT1); inOrder.verify(statement1).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement2).execute(CREATE_STATEMENT2); inOrder.verify(statement2).close(); assertEquals(4, loggingEvents.size()); assertLog(0, DEBUG, "Executing SQL: " + CREATE_STATEMENT1); assertLog(1, DEBUG, "Executing SQL: " + CREATE_STATEMENT2); assertLog(2, WARN, "Could not create JDBC tables; they could already exist. Failure was: " + CREATE_STATEMENT2 + " Message: " + MY_REASON + " SQLState: " + SQL_STATE + " Vendor code: " + VENDOR_CODE); assertLog(3, WARN, "Failure details: " + MY_REASON); } @Test public void triesTocreateTheTablesWhenMessageTableExistsAndLogsSqlExceptionsInDebugLevel() throws SQLException, IOException { when(resultSet.next()).thenReturn(true); when(statement1.execute(CREATE_STATEMENT1)).thenThrow(new SQLException(MY_REASON, SQL_STATE, VENDOR_CODE)); defaultJDBCAdapter.doCreateTables(transactionContext); InOrder inOrder = inOrder(resultSet, connection, statement1, statement2); inOrder.verify(resultSet).next(); inOrder.verify(resultSet).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement1).execute(CREATE_STATEMENT1); inOrder.verify(statement1).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement2).execute(CREATE_STATEMENT2); inOrder.verify(statement2).close(); assertEquals(3, loggingEvents.size()); assertLog(0, DEBUG, "Executing SQL: " + CREATE_STATEMENT1); assertLog(1, DEBUG, "Could not create JDBC tables; The message table already existed. Failure was: " + CREATE_STATEMENT1 + " Message: " + MY_REASON + " SQLState: " + SQL_STATE + " Vendor code: " + VENDOR_CODE); assertLog(2, DEBUG, "Executing SQL: " + CREATE_STATEMENT2); } @Test public void commitsTheTransactionWhenAutoCommitIsDisabled() throws SQLException, IOException { when(connection.getAutoCommit()).thenReturn(false); when(resultSet.next()).thenReturn(false); defaultJDBCAdapter.doCreateTables(transactionContext); InOrder inOrder = inOrder(resultSet, connection, statement1, statement2); inOrder.verify(resultSet).next(); inOrder.verify(resultSet).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement1).execute(CREATE_STATEMENT1); inOrder.verify(connection).commit(); inOrder.verify(statement1).close(); inOrder.verify(connection).createStatement(); inOrder.verify(statement2).execute(CREATE_STATEMENT2); inOrder.verify(connection).commit(); inOrder.verify(statement2).close(); assertEquals(2, loggingEvents.size()); assertLog(0, DEBUG, "Executing SQL: " + CREATE_STATEMENT1); assertLog(1, DEBUG, "Executing SQL: " + CREATE_STATEMENT2); } private void assertLog(int messageNumber, Level level, String message) { LoggingEvent loggingEvent = loggingEvents.get(messageNumber); assertEquals(level, loggingEvent.getLevel()); assertEquals(message, loggingEvent.getMessage()); } }