package net.codjo.control.server.plugin;
import net.codjo.aspect.Aspect;
import net.codjo.aspect.AspectContext;
import net.codjo.aspect.AspectException;
import net.codjo.aspect.AspectManager;
import net.codjo.aspect.JoinPoint;
import net.codjo.control.common.ControlContext;
import net.codjo.control.common.ControlException;
import net.codjo.control.common.IntegrationPlan;
import net.codjo.control.common.message.ControlJobRequest;
import net.codjo.control.server.api.ControlAspectContext;
import net.codjo.database.common.api.DatabaseFactory;
import net.codjo.database.common.api.JdbcFixture;
import net.codjo.test.common.LogString;
import net.codjo.test.common.mock.ConnectionMock;
import java.sql.Connection;
import java.sql.SQLException;
import junit.framework.TestCase;
public class QuarantineControlManagerTest extends TestCase {
private static final String CONTROL_TABLE = "CTRL_TABLE";
private static final String QUARANTINE_TABLE = "Q_VL";
private JdbcFixture jdbc;
private LogString log = new LogString();
private Connection connection = new ConnectionMock().getStub();
private QuarantineControlManager controlManager;
private IntegrationPlanMock planMock;
private AspectManager manager;
@Override
protected void setUp() throws Exception {
jdbc = new DatabaseFactory().createJdbcFixture();
manager = new AspectManager();
planMock = new IntegrationPlanMock();
ControlPreference controlPreference = new ControlPreference(null, manager) {
@Override
public IntegrationPlan getPlan(String quarantineTable) {
return planMock;
}
};
controlManager = new QuarantineControlManager(controlPreference);
jdbc.doSetUp();
}
@Override
protected void tearDown() throws Exception {
jdbc.doTearDown();
}
public void test_execute() throws Exception {
createTable(QUARANTINE_TABLE);
jdbc.executeUpdate("insert into " + QUARANTINE_TABLE + " values (1, 0, null)");
jdbc.executeUpdate("insert into " + QUARANTINE_TABLE + " values (2, 0, null)");
jdbc.executeUpdate("insert into " + QUARANTINE_TABLE + " values (3, 0, null)");
planMock.mockExecuteBatchControls("update " + CONTROL_TABLE + " set ERROR_TYPE=5 where Q_ID=2");
ControlJobRequest jobRequest = new ControlJobRequest(QUARANTINE_TABLE);
jobRequest.setInitiatorLogin("user");
jobRequest.setId("control-2");
jobRequest.addPath("p1");
PostControlAudit postControlAudit =
controlManager.doQuarantineControls(jdbc.getConnection(), jobRequest);
jdbc.assertContent(net.codjo.database.common.api.structure.SqlTable.table(QUARANTINE_TABLE),
new String[][]{
{"1", "0", null}
, {"2", "5", null}
, {"3", "0", null}
});
log.assertContent("executeShipmemt()"
+ ", executeBatchControls(context:user/control-2)"
+ ", executeDispatch()");
assertNotNull(postControlAudit);
assertEquals(2, postControlAudit.getValidLineCount());
assertEquals(1, postControlAudit.getBadLineCount());
}
public void test_execute_technicalError() throws Exception {
createTable(QUARANTINE_TABLE);
jdbc.executeUpdate("insert into " + QUARANTINE_TABLE + " values (1, 0, null)");
planMock.mockExecuteBatchControlsFailure(new SQLException("bad sql statement"));
ControlJobRequest jobRequest = new ControlJobRequest(QUARANTINE_TABLE);
jobRequest.setInitiatorLogin("user");
jobRequest.setId("control-2");
jobRequest.addPath("p1");
try {
controlManager.doQuarantineControls(jdbc.getConnection(), jobRequest);
fail();
}
catch (QuarantineControlException ex) {
assertEquals("java.sql.SQLException: bad sql statement", ex.getMessage());
assertNotNull(ex.getCause());
}
jdbc.assertContent(net.codjo.database.common.api.structure.SqlTable.table(QUARANTINE_TABLE),
new String[][]{
{"1", "499", "ERREUR TECHNIQUE : bad sql statement"}
});
}
public void test_executeDispatch_aspect() throws Exception {
// Aspect
manager.addAspect("aspectBefore",
newJoinPoint(JoinPoint.CALL_BEFORE, "control.dispatch", QUARANTINE_TABLE),
FakeBeforeAspect.class);
// Appel
controlManager.executeDispatch(planMock, createContext("user", "myCurrentRequestId"));
// Verification de l'appel
assertEquals("setUp, run, cleanUp", FakeBeforeAspect.executeList.toString());
// Verification du contexte
ControlAspectContext context = new ControlAspectContext(FakeBeforeAspect.aspectCtxt);
assertNotNull(FakeBeforeAspect.aspectCtxt);
assertSame(connection, context.getConnection());
assertEquals("user", context.getUser());
assertEquals(CONTROL_TABLE, context.getControlTableName());
assertEquals("myCurrentRequestId", context.getJobRequestId());
}
public void test_getTechnicalErrorMessage() throws Exception {
assertEquals("ERREUR TECHNIQUE : Erreur",
controlManager.getTechnicalErrorMessage(new RuntimeException("Erreur")));
assertEquals(254,
controlManager
.getTechnicalErrorMessage(new RuntimeException(new String(new char[600])))
.length());
}
public void test_getTechnicalErrorMessage_null() throws Exception {
assertEquals("ERREUR TECHNIQUE : java.lang.RuntimeException",
controlManager.getTechnicalErrorMessage(new RuntimeException((String)null)));
}
private ControlAspectContext createContext(String user, String requestId) {
ControlAspectContext context = new ControlAspectContext();
context.setUser(user);
context.setJobRequestId(requestId);
context.setConnection(connection);
context.setControlTableName(CONTROL_TABLE);
context.setQuarantineTable(QUARANTINE_TABLE);
return context;
}
private JoinPoint[] newJoinPoint(int call, String point, String argument) {
JoinPoint joinPoint = new JoinPoint();
joinPoint.setArgument(argument);
joinPoint.setPoint(point);
joinPoint.setCall(call);
return new JoinPoint[]{joinPoint};
}
private void createTable(String tableName) throws SQLException {
jdbc.create(net.codjo.database.common.api.structure.SqlTable.table(tableName), "Q_ID int not null, "
+ "ERROR_TYPE int null, "
+ "ERROR_LOG varchar(255) null");
}
public static class FakeBeforeAspect implements Aspect {
/**
* @noinspection StaticNonFinalField
*/
private static StringBuffer executeList = null;
/**
* @noinspection StaticNonFinalField
*/
private static AspectContext aspectCtxt = null;
public void setUp(AspectContext context, JoinPoint joinPoint)
throws AspectException {
executeList = new StringBuffer();
executeList.append("setUp");
aspectCtxt = context;
}
public void run(AspectContext context) throws AspectException {
executeList.append(", run");
}
public void cleanUp(AspectContext context)
throws AspectException {
executeList.append(", cleanUp");
}
}
private class IntegrationPlanMock extends IntegrationPlan {
private SQLException batchControlsFatalFailure;
private String batchControlQuery;
@Override
public void executeShipmemt(final Connection connection) throws SQLException {
log.call("executeShipmemt");
createTable(CONTROL_TABLE);
connection.createStatement().executeUpdate("insert into " + CONTROL_TABLE +
" select * from " + QUARANTINE_TABLE);
}
@Override
public void executeDispatch(Connection connection, ControlContext context) throws SQLException {
log.call("executeDispatch");
if (QuarantineControlManagerTest.this.connection == connection) {
return;
}
// NB : HSQLDB ne supporte pas les requetes "update ... from ... inner"
connection.createStatement().executeUpdate("update " + QUARANTINE_TABLE
+ " set ERROR_TYPE = ( "
+ "select ERROR_TYPE from " + CONTROL_TABLE
+ " where " + CONTROL_TABLE + ".Q_ID = "
+ QUARANTINE_TABLE + ".Q_ID)");
}
@Override
public void executeBatchControls(final Connection connection, final ControlContext context)
throws SQLException, ControlException {
log.call("executeBatchControls",
"context:" + context.getUser() + "/" + context.getCurrentRequestId());
if (batchControlQuery != null) {
connection.createStatement().executeUpdate(batchControlQuery);
}
if (batchControlsFatalFailure != null) {
batchControlsFatalFailure.fillInStackTrace();
throw batchControlsFatalFailure;
}
}
@Override
public String getControlTableName() {
return CONTROL_TABLE;
}
@Override
public String getQuarantineTable() {
return QUARANTINE_TABLE;
}
public void mockExecuteBatchControlsFailure(SQLException failure) {
batchControlsFatalFailure = failure;
}
public void mockExecuteBatchControls(String query) {
batchControlQuery = query;
}
}
}