package com.goodworkalan.addendum;
import static com.goodworkalan.addendum.Addendum.SQL_ADDENDA_COUNT;
import static com.goodworkalan.addendum.Addendum.SQL_ADDENDUM;
import static com.goodworkalan.addendum.Addendum.SQL_CREATE_ADDENDA;
import static com.goodworkalan.addendum.Addendum.SQL_GET_DIALECT;
import static org.testng.AssertJUnit.assertEquals;
import java.sql.Connection;
import java.sql.SQLException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.goodworkalan.addendum.connector.MockConnector;
import com.goodworkalan.addendum.dialect.Dialect;
import com.goodworkalan.addendum.dialect.MockDatabase;
import com.goodworkalan.danger.Danger;
import com.goodworkalan.danger.test.Dangerous;
/**
* Unit tests for the {@link Addenda} class.
*
* @author Alan Gutierrez
*/
public class AddendaTest {
/** Reset the mock database before running a test. */
@BeforeMethod
public void resetDatabase() {
MockDatabase.clear();
}
/** The constructor creates a new instance of an addenda. */
@Test
public void constructor() {
new Addenda(new MockConnector());
}
/**
* Run a block of code that raises an <code>Danger</code> and assert the
* values of the exception code and message.
*
* @param runnable
* The block of code.
* @param code
* The expected error code.
* @param message
* The expected error message.
*/
public static void exceptional(Runnable runnable, String code, String message) {
try {
runnable.run();
} catch (Danger e) {
assertEquals(e.code, code);
assertEquals(e.getMessage(), message);
throw e;
}
}
/**
* An <code>SQLException</code> thrown from
* {@link Dialect#canTranslate(java.sql.Connection, Dialect) is wrapped in a
* <code>Danger</code> and thrown.
*/
@Test(expectedExceptions = Danger.class)
public void getDialectSQLException() throws SQLException {
Dangerous.danger(new Runnable() {
public void run() {
new Addenda(new MockConnector("ERROR")).amend();
}
}, Addendum.class, SQL_GET_DIALECT, SQLException.class, "Unable to create the database dialect.");
}
/** Test the failure of the creation of a {@link Definition}. */
@Test(expectedExceptions = Danger.class)
public void getDialectMissing() throws SQLException {
Dangerous.danger(new Runnable() {
public void run() {
new Addenda(new MockConnector("MISMATCH")).amend();
}
}, Addendum.class, SQL_GET_DIALECT, null, "Unable to create the database dialect.");
}
/**
* When the Addenda table cannot be created a <code>Danger</code> exception
* is thrown.
*/
@Test(expectedExceptions = Danger.class)
public void unableToCreateAddendaTable() {
Dangerous.danger(new Runnable() {
public void run() {
new Addenda(new MockConnector("FAIL_ON_CREATE_ADDENDA_TABLE")).amend();
}
}, Addendum.class, SQL_CREATE_ADDENDA, SQLException.class, "Unable to create the addenda table to track updates.");
}
/**
* When the addenda count cannot be fetched from the Addenda table a
* <code>Danger</code> exception is thrown.
*/
@Test(expectedExceptions = Danger.class)
public void unableToGetAddedaCount() {
Dangerous.danger(new Runnable() {
public void run() {
new Addenda(new MockConnector("FAIL_ON_ADDENDA_COUNT")).amend();
}
}, Addendum.class, SQL_ADDENDA_COUNT, SQLException.class, "Unable to fetch the maximum value of the applied updates from the addenda table.");
}
/**
* When the addenda count cannot be fetched from the Addenda table a
* <code>Danger</code> exception is thrown.
*/
@Test(expectedExceptions = Danger.class)
public void unableToInsertAddendum() {
Dangerous.danger(new Runnable() {
public void run() {
Addenda addenda = new Addenda(new MockConnector("FAIL_ON_ADDENDUM"));
addenda.addendum();
addenda.amend();
}
}, Addendum.class, SQL_ADDENDUM, SQLException.class, "Unable to insert a new addenda into the the addenda table.");
}
/**
* Create person and address entity definitions.
*
* @param addenda
* The addenda.
*/
private void createPersonAndAddress(Addenda addenda) {
addenda
.addendum()
.define("Person")
.add("firstName", String.class).length(64).end()
.add("lastName", String.class).length(64).end()
.end()
.define("Address")
.add("address", String.class).length(64).end()
.add("city", String.class).length(64).end()
.add("state", String.class).length(64).end()
.add("zip", String.class).length(64).end()
.end()
.insert("Person")
.columns("firstName", "lastName").values("Alan", "Gutierrez");
}
/**
* An empty amend completes successfully without throwing exceptions.
*/
@Test
public void emptyAmend() {
Addenda addenda = new Addenda(new MockConnector());
addenda.addendum();
addenda.amend();
assertEquals(1, MockDatabase.INSTANCE.addenda.size());
}
/**
* Create a new connector with the given H2 database path.
*
* @param database
* The database path.
* @return A new connector.
*/
// @Test
public void tiny() throws ClassNotFoundException, SQLException {
Addenda addenda = new Addenda(new MockConnector());
createPersonAndAddress(addenda);
addenda.amend();
}
/** Test the existence of the addenda table. */
// @Test
public void addendaTableExists()
throws ClassNotFoundException, SQLException {
Addenda addenda = new Addenda(new MockConnector());
createPersonAndAddress(addenda);
addenda.amend();
addenda.amend();
}
/** Test a basic migration. */
// @Test
public void basic() {
Addenda addenda = new Addenda(new MockConnector());
new ExampleMigration(addenda).create();
}
/**
* A skipped addendum is not invoked. If the skipped addendum were invoked,
* an exception would be thrown by this test.
*/
@Test
public void skip() {
Addenda addenda = new Addenda(new MockConnector(), 1);
addenda
.addendum()
.execute(new Executable() {
public void execute(Connection connection, Dialect dialect) {
throw new RuntimeException();
}
})
.commit();
addenda.amend();
assertEquals(1, MockDatabase.INSTANCE.addenda.size());
}
}
/* vim: set nowrap: */