package br.com.citframework.integracao.core;
import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import br.com.citframework.util.ReflectionUtils;
/**
* Classe de testes para valida��o do comportamento de {@link SequenceBlockCache}
*
* @author bruno.ribeiro - <a href="mailto:bruno.ribeiro@centrait.com.br">bruno.ribeiro@centrait.com.br</a>
* @since 18/08/2014
*
*/
public final class SequenceBlockCacheTest {
private static Connection connection = null;
private static volatile SequenceBlockCache globalCache;
private final int INCREMENT = 10;
private final int NEGATIVE_INCREMENT = -1;
private final long INTERACTIONS = 500;
private static final String TRUNCATE_TABLE = "truncate table %s";
private static final String DROP_TABLE_IF_EXISTS = "drop table if exists %s";
private static final String TABLE_CONTROLLER = "sequence_block_controller";
private static final String TABLE_ONE = "table_one";
private static final String TABLE_ONE_COLUMN_ONE = "id_one_table_one";
private static final String TABLE_TWO = "table_two";
private static final String TABLE_TWO_COLUMN_ONE = "id_one_table_two";
private static final String TABLE_TWO_COLUMN_TWO = "id_two_table_two";
private static final String EMBEDDED_JAVADB_JDBC_CLASS = "org.h2.Driver";
private static final String EMBEDDED_JAVADB_JDBC_URL = "jdbc:h2:~/test";
private static String getDDLSequenceController() {
final StringBuilder sql = new StringBuilder();
sql.append("create table sequence_block_controller (");
sql.append(" id identity primary key,");
sql.append(" sequence_name varchar(60) not null,");
sql.append(" last_id bigint not null");
sql.append(");");
sql.append("alter table sequence_block_controller add constraint sequence_block_controller_key unique(sequence_name);");
return sql.toString();
}
@BeforeClass
public static void setUpClass() throws Exception {
final Constructor<SequenceBlockCache> construct = SequenceBlockCache.class.getDeclaredConstructor();
construct.setAccessible(true);
globalCache = construct.newInstance();
try (Statement stmt = getConnection().createStatement()) {
stmt.executeUpdate(String.format(DROP_TABLE_IF_EXISTS, TABLE_ONE));
stmt.executeUpdate(String.format(DROP_TABLE_IF_EXISTS, TABLE_TWO));
stmt.executeUpdate(String.format(DROP_TABLE_IF_EXISTS, TABLE_CONTROLLER));
}
try (Statement stmt = getConnection().createStatement()) {
stmt.executeUpdate(String.format("create table %s (%s int)", TABLE_ONE, TABLE_ONE_COLUMN_ONE));
stmt.executeUpdate(String.format("create table %s (%s int, %s int)", TABLE_TWO, TABLE_TWO_COLUMN_ONE, TABLE_TWO_COLUMN_TWO));
stmt.executeUpdate(getDDLSequenceController());
}
}
@Before
public void setUp() throws Exception {
try (Statement stmt = getConnection().createStatement()) {
stmt.executeUpdate(String.format(TRUNCATE_TABLE, TABLE_ONE));
stmt.executeUpdate(String.format(TRUNCATE_TABLE, TABLE_TWO));
stmt.executeUpdate(String.format(TRUNCATE_TABLE, TABLE_CONTROLLER));
}
}
@Test
public void testSequenceBlockCacheNextIdTableOne() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextId = this.nextID(TABLE_ONE, TABLE_ONE_COLUMN_ONE);
this.insertIntoTable(nextId);
Assert.assertEquals(nextId, i);
}
}
@Test
public void testSequenceBlockCacheNextIdTableTwo() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextIdColumnOne = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_ONE);
final long nextIdColumnTwo = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_TWO);
this.insertIntoTableTwo(nextIdColumnOne, nextIdColumnTwo);
Assert.assertEquals(nextIdColumnOne, i);
Assert.assertEquals(nextIdColumnTwo, i);
}
}
@Test
public void testSequenceBlockCacheNextIdWithIncrementTableOne() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextId = this.nextID(TABLE_ONE, TABLE_ONE_COLUMN_ONE, INCREMENT);
this.insertIntoTable(nextId);
Assert.assertEquals(nextId, i);
}
}
@Test
public void testSequenceBlockCacheNextIdWithIncrementTableTwo() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextIdColumnOne = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_ONE, INCREMENT);
final long nextIdColumnTwo = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_TWO, INCREMENT);
this.insertIntoTableTwo(nextIdColumnOne, nextIdColumnTwo);
Assert.assertEquals(nextIdColumnOne, i);
Assert.assertEquals(nextIdColumnTwo, i);
}
}
@Test
public void testSequenceBlockCacheNextIdWithNegativeIncrementTableOne() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextId = this.nextID(TABLE_ONE, TABLE_ONE_COLUMN_ONE, NEGATIVE_INCREMENT);
this.insertIntoTable(nextId);
Assert.assertEquals(nextId, i);
}
}
@Test
public void testSequenceBlockCacheNextIdWithNegativeIncrementTableTwo() throws Exception {
for (long i = 1; i <= INTERACTIONS; i++) {
final long nextIdColumnOne = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_ONE, NEGATIVE_INCREMENT);
final long nextIdColumnTwo = this.nextID(TABLE_TWO, TABLE_TWO_COLUMN_TWO, NEGATIVE_INCREMENT);
this.insertIntoTableTwo(nextIdColumnOne, nextIdColumnTwo);
Assert.assertEquals(nextIdColumnOne, i);
Assert.assertEquals(nextIdColumnTwo, i);
}
}
private void insertIntoTable(final Long valueColumnOne) throws SQLException {
final String sql = String.format("insert into %s (%s) values (?)", TABLE_ONE, TABLE_ONE_COLUMN_ONE);
try (PreparedStatement stmt = getConnection().prepareStatement(sql)) {
stmt.setInt(1, valueColumnOne.intValue());
stmt.execute();
}
}
private void insertIntoTableTwo(final Long valueColumnOne, final Long valueColumnTwo) throws SQLException {
final String sql = String.format("insert into %s (%s, %s) values (?, ?)", TABLE_TWO, TABLE_TWO_COLUMN_ONE, TABLE_TWO_COLUMN_TWO);
try (PreparedStatement stmt = getConnection().prepareStatement(sql)) {
stmt.setInt(1, valueColumnOne.intValue());
stmt.setInt(2, valueColumnTwo.intValue());
stmt.execute();
}
}
private long nextID(final String tableName, final String columnName) {
getConnection();
return globalCache.getNextId(tableName, columnName);
}
private long nextID(final String tableName, final String columnName, final int increment) {
getConnection();
return globalCache.getNextId(tableName, columnName, increment);
}
private static Connection getConnection() {
try {
if (connection == null || connection.isClosed()) {
Class.forName(EMBEDDED_JAVADB_JDBC_CLASS);
connection = DriverManager.getConnection(EMBEDDED_JAVADB_JDBC_URL);
ReflectionUtils.setField(globalCache, "connection", connection);
}
} catch (final Exception e) {}
return connection;
}
@AfterClass
public static void tearDownClass() throws Exception {
if (getConnection() != null && !getConnection().isClosed()) {
getConnection().close();
}
}
}