/*
* -----------------------------------------------------------------------\
* PerfCake
*
* Copyright (C) 2010 - 2016 the original author or authors.
*
* Licensed 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.perfcake.message.sender;
import static org.mockito.Mockito.*;
import org.perfcake.util.ObjectFactory;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.ErrorHandler;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* Tests {@link org.perfcake.message.sender.JdbcSender}.
*
* @author <a href="mailto:lenka@vecerovi.com">Lenka Večeřa</a>
*/
@Test(groups = { "unit" })
public class JdbcSenderTest {
private static class DebugLogAppender implements Appender {
private String lastMessage = null;
@Override
public void append(final LogEvent logEvent) {
lastMessage = logEvent.getMessage().getFormattedMessage();
}
@Override
public String getName() {
return "DebugAppender";
}
@Override
public Layout<? extends Serializable> getLayout() {
return null;
}
@Override
public boolean ignoreExceptions() {
return false;
}
@Override
public ErrorHandler getHandler() {
return null;
}
@Override
public void setHandler(final ErrorHandler errorHandler) {
}
@Override
public State getState() {
return State.STARTED;
}
@Override
public void initialize() {
}
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public boolean isStarted() {
return true;
}
@Override
public boolean isStopped() {
return false;
}
}
@Test
public void testSelect() throws Exception {
final String sql = "SELECT * FROM USERS";
final String result = "1;Jennifer Aniston;jennifer@aniston.com\n2;Adam Sandler;adam0001@yahoo.com";
final Connection c = mock(Connection.class);
final Statement s = mock(Statement.class);
final ResultSet rs = mock(ResultSet.class);
final ResultSetMetaData rsmd = mock(ResultSetMetaData.class);
when(c.createStatement()).thenReturn(s);
when(s.execute(sql)).thenReturn(true);
when(s.getResultSet()).thenReturn(rs);
when(rs.getMetaData()).thenReturn(rsmd);
when(rsmd.getColumnCount()).thenReturn(3);
when(rsmd.getColumnName(1)).thenReturn("ID");
when(rsmd.getColumnName(2)).thenReturn("NAME");
when(rsmd.getColumnName(3)).thenReturn("EMAIL");
when(rsmd.getColumnTypeName(1)).thenReturn("Long");
when(rsmd.getColumnTypeName(2)).thenReturn("String");
when(rsmd.getColumnTypeName(3)).thenReturn("String");
when(rs.getFetchSize()).thenReturn(1);
when(rs.toString()).thenReturn(result);
when(rs.next()).thenAnswer(new Answer<Boolean>() {
private int count = 0;
public Boolean answer(final InvocationOnMock invocation) {
return count++ < 2;
}
});
final Properties props = new Properties();
final JdbcSender sender = (JdbcSender) ObjectFactory.summonInstance(JdbcSender.class.getName(), props);
// Inject connection
final Field connectionField = JdbcSender.class.getDeclaredField("connection");
connectionField.setAccessible(true);
connectionField.set(sender, c);
final org.perfcake.message.Message message = new org.perfcake.message.Message();
message.setPayload(sql);
sender.preSend(message, null);
final Serializable response = sender.send(message, null);
sender.postSend(message);
sender.close();
Assert.assertEquals(response.toString(), result);
final InOrder order = inOrder(c, s, rs, rsmd);
order.verify(c).createStatement();
order.verify(s).execute(sql);
order.verify(s).getResultSet();
order.verify(rs).getMetaData();
order.verify(rsmd).getColumnCount();
verify(rsmd, never()).getColumnType(0);
verify(rsmd, never()).getColumnType(4);
verify(rsmd, never()).getColumnTypeName(0);
verify(rsmd, never()).getColumnTypeName(4);
verify(rs, times(1)).getFetchSize();
verify(rs, times(3)).next();
verify(rsmd).getColumnName(1);
verify(rsmd).getColumnName(2);
verify(rsmd).getColumnName(3);
verify(rsmd).getColumnTypeName(1);
verify(rsmd).getColumnTypeName(2);
verify(rsmd).getColumnTypeName(3);
verify(s).close();
verify(c).close();
verifyNoMoreInteractions(c, s, rs, rsmd);
}
@Test
public void testUpdate() throws Exception {
final String sql = "DROP TABLE USERS";
final Connection c = mock(Connection.class);
final Statement s = mock(Statement.class);
when(c.createStatement()).thenReturn(s);
when(s.execute(sql)).thenReturn(false);
when(s.getUpdateCount()).thenReturn(3);
final Properties props = new Properties();
final JdbcSender sender = (JdbcSender) ObjectFactory.summonInstance(JdbcSender.class.getName(), props);
// Inject connection
final Field connectionField = JdbcSender.class.getDeclaredField("connection");
connectionField.setAccessible(true);
connectionField.set(sender, c);
final org.perfcake.message.Message message = new org.perfcake.message.Message();
message.setPayload(sql);
sender.preSend(message, null);
final Serializable response = sender.send(message, null);
sender.postSend(message);
sender.close();
Assert.assertEquals(response, 3);
final InOrder order = inOrder(c, s);
order.verify(c).createStatement();
order.verify(s).execute(sql);
order.verify(s).getUpdateCount();
verify(s).close();
verify(c).close();
verifyNoMoreInteractions(c, s);
}
@Test
public void testProperties() throws Exception {
final String username = "zappa";
final String password = "frank";
final String jdbcUrl = "jdbc:none:test";
final String driverClass = "org.perfcake.None";
final Properties props = new Properties();
props.setProperty("username", username);
props.setProperty("password", password);
props.setProperty("jdbcUrl", jdbcUrl);
props.setProperty("driverClass", driverClass);
final JdbcSender sender = (JdbcSender) ObjectFactory.summonInstance(JdbcSender.class.getName(), props);
Assert.assertEquals(sender.getUsername(), username);
Assert.assertEquals(sender.getPassword(), password);
Assert.assertEquals(sender.getJdbcUrl(), jdbcUrl);
Assert.assertEquals(sender.getDriverClass(), driverClass);
}
@Test
public void testNegativeClose() throws Exception {
final String errorMessage = "Huhúúú";
final Connection c = mock(Connection.class);
doThrow(new SQLException(errorMessage)).when(c).close();
final Properties props = new Properties();
final JdbcSender sender = (JdbcSender) ObjectFactory.summonInstance(JdbcSender.class.getName(), props);
// Inject connection
final Field connectionField = JdbcSender.class.getDeclaredField("connection");
connectionField.setAccessible(true);
connectionField.set(sender, c);
// Add log appender
final Field logField = JdbcSender.class.getDeclaredField("log");
logField.setAccessible(true);
final Logger log = (Logger) logField.get(sender);
final DebugLogAppender a = new DebugLogAppender();
((org.apache.logging.log4j.core.Logger) log).addAppender(a);
sender.close();
Assert.assertEquals(a.lastMessage, "Unable to close JDBC connection: " + errorMessage);
verify(c).close();
verifyNoMoreInteractions(c);
}
}