Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.etlunit.feature.database.DbAssertExtender Maven / Gradle / Ivy
package org.etlunit.feature.database;
import org.etlunit.*;
import org.etlunit.context.VariableContext;
import org.etlunit.feature.Feature;
import org.etlunit.feature.RuntimeOption;
import org.etlunit.feature.assertion.Assertion;
import org.etlunit.io.file.*;
import org.etlunit.feature.extend.Extender;
import org.etlunit.parser.ETLTestOperation;
import org.etlunit.parser.ETLTestValueObject;
import org.etlunit.parser.ETLTestValueObjectBuilder;
import org.etlunit.util.IOUtils;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
import java.sql.Types;
import java.util.*;
public class DbAssertExtender implements Extender, AssertOperationProcessor
{
private DataFileManager dataFileManager;
private DiffManager diffManager;
private final DatabaseFeatureModule parent;
private final DatabaseConfiguration databaseConfiguration;
private DatabaseRuntimeSupport databaseRuntimeSupport;
private boolean refreshAssertionData = false;
protected Log applicationLog;
private Map columnTypes;
private List columns;
public DbAssertExtender(DatabaseFeatureModule parent)
{
this.parent = parent;
databaseConfiguration = parent.getDatabaseConfiguration();
columns = Arrays.asList("ROW_NUMBER", "COLUMN_NAME", "SOURCE", "TARGET");
columnTypes = new HashMap();
columnTypes.put("ROW_NUMBER", Types.INTEGER);
columnTypes.put("COLUMN_NAME", Types.VARCHAR);
columnTypes.put("SOURCE", Types.VARCHAR);
columnTypes.put("TARGET", Types.VARCHAR);
}
@Inject
public void receiveDataFileManager(DataFileManager manager)
{
dataFileManager = manager;
}
@Inject
public void setExportSAssertionData(@Named("database.refreshAssertionData") RuntimeOption option)
{
refreshAssertionData = option.isEnabled();
applicationLog.info(refreshAssertionData ? "Refreshing assertion data" : "Not refreshing assertion data");
}
@Inject
public void setApplicationLog(@Named("applicationLog") Log log)
{
applicationLog = log;
}
@Inject
public void setDatabaseRuntimeSupport(DatabaseRuntimeSupport databaseRuntimeSupport)
{
this.databaseRuntimeSupport = databaseRuntimeSupport;
}
@Inject
public void receiveDiffManager(DiffManager reporter)
{
diffManager = reporter;
}
public boolean canHandleRequest(ETLTestOperation operation, ETLTestValueObject operands, VariableContext context, ExecutionContext executionContext)
{
return operands.query("source-table") != null;
}
public ClassResponder.action_code process(ETLTestOperation op, ETLTestValueObject operands, VariableContext context, ExecutionContext executionContext) throws TestAssertionFailure, TestExecutionError, TestWarning
{
return action_code.defer;
}
public Feature getFeature()
{
return parent;
}
public action_code processAssert(AssertOperation operation, ETLTestOperation op, ETLTestValueObject obj, VariableContext context, ExecutionContext econtext) throws TestAssertionFailure, TestExecutionError, TestWarning
{
AssertOperation.assertionMode_enum a_mode = operation.getAssertionMode();
final Assertion.assertion_mode comparisonMode;
if (a_mode == null)
{
comparisonMode = Assertion.assertion_mode.equals;
}
else
{
switch (a_mode)
{
case equals:
comparisonMode = Assertion.assertion_mode.equals;
break;
case empty:
comparisonMode = Assertion.assertion_mode.empty;
break;
case notEmpty:
comparisonMode = Assertion.assertion_mode.not_empty;
break;
default:
throw new TestExecutionError("Invalid assertion mode: " + a_mode, DatabaseConstants.ERR_INVALID_ASSERTION_MODE);
}
}
// check the runtime option for refresh data. If so, convert this call into an extract operation for the assert equals case
if (refreshAssertionData && comparisonMode == Assertion.assertion_mode.equals)
{
ETLTestValueObject copy = obj.copy();
ETLTestValueObjectBuilder cbuilder = new ETLTestValueObjectBuilder(copy);
// get rid of assertion mode and failure-id
if (copy.query(AssertOperation.ASSERTIONMODE_JSON_NAME) != null)
{
cbuilder.removeKey(AssertOperation.ASSERTIONMODE_JSON_NAME);
}
if (copy.query(AssertOperation.FAILUREID_JSON_NAME) != null)
{
cbuilder.removeKey(AssertOperation.FAILUREID_JSON_NAME);
}
copy = cbuilder.toObject();
ETLTestOperation extract_op = op.createSibling("extract", copy);
econtext.process(extract_op, context);
return ClassResponder.action_code.handled;
}
String sourceTable = operation.getSourceTable();
String failureId = operation.getFailureId();
String qualifiedName = sourceTable;
String schema = operation.getSourceSchema();
if (schema != null)
{
qualifiedName = schema + "." + sourceTable;
}
DatabaseClassListener.ConnectionMode connMode = DatabaseClassListener.getConnection(parent, obj, context, op.getTestMethod()).get(0);
final DatabaseConnection conn = connMode.conn;
final String mode = connMode.getMode();
// now send it off to the implementation
DatabaseImplementation impl = DatabaseClassListener.getDatabaseImplementation(parent, conn);
// dispatch this as an operation (even though this feature will ultimately process)
ETLTestValueObject copy = obj.copy();
String tar = operation.getTarget();
File target;
// create a target file attribute for our extract
if (tar != null)
{
target = databaseRuntimeSupport.getGeneratedDataSet(conn, connMode.getPrettyMode(), op.getTestMethod().getQualifiedName() + "_tgt_" + tar, DatabaseImplementation.data_format.delimited);
}
else
{
target = databaseRuntimeSupport.getGeneratedDataSet(conn, connMode.getPrettyMode(), sourceTable + "_" + conn.getDatabaseName(mode) + "_" + op.getTestMethod().getName(), DatabaseImplementation.data_format.delimited);
}
// remove the assertion-mode attribute since it does not pass validation
// for the extract operation
ETLTestValueObjectBuilder cbuilder = new ETLTestValueObjectBuilder(copy);
if (copy.query("assertion-mode") != null)
{
cbuilder = cbuilder.removeKey("assertion-mode");
}
if (copy.query("failure-id") != null)
{
cbuilder = cbuilder.removeKey("failure-id");
}
cbuilder = cbuilder.key("target-file")
.value(target.getAbsolutePath());
copy = cbuilder.toObject();
ETLTestOperation extract_op = op.createSibling("extract", copy);
econtext.process(extract_op, context);
DataFileSchema ffs = null;
// grab the schema the extract produced
if (context.hasVariableBeenDeclared(DatabaseClassListener.LAST_EXTRACT_FILE_SCHEMA))
{
ffs = (DataFileSchema) context.getValue(DatabaseClassListener.LAST_EXTRACT_FILE_SCHEMA).getValueAsPojo();
}
switch (comparisonMode)
{
case equals:
{
String synthFailureId = connMode.connectionId + "." + connMode.getPrettyMode() + "." + schema + "." + operation.getTarget();
if (tar == null)
{
throw new TestExecutionError("Assert equals requires a target argument", DatabaseConstants.ERR_ASSERT_MISSING_TARGET);
}
// compare to the file in the test folder
File testFile = databaseRuntimeSupport.getSourceDataSet(op.getTestClass().getPackage(), tar, DatabaseImplementation.data_format.delimited);
boolean matching = false;
List diffReport = null;
try
{
DataFile fSource = dataFileManager.loadDataFile(testFile, ffs);
File dataSetLocal = databaseRuntimeSupport.getGeneratedDataSet(conn, connMode.getPrettyMode(), op.getTestMethod().getQualifiedName() + "_src_" + IOUtils.removeExtension(testFile.getName()), DatabaseImplementation.data_format.delimited);
applicationLog.info("Creating cache copy of " + testFile.getAbsolutePath() + "] to [" + dataSetLocal.getAbsolutePath() + "]");
DataFile lSource = dataFileManager.loadDataFile(dataSetLocal, ffs);
// copy to local cache
dataFileManager.copyDataFile(fSource, lSource);
DataFile fTarget = dataFileManager.loadDataFile(target, ffs);
applicationLog.info("Asserting equality of [" + lSource.getSource().getAbsolutePath() + "] and [" + fTarget.getSource().getAbsolutePath() + "]");
String variableName = "extract.columns." + tar;
applicationLog.info("Reading extract column list for " + variableName);
ETLTestValueObject value = context.getValue(variableName);
if (value == null)
{
throw new TestExecutionError("", DatabaseConstants.ERR_MISSING_COL_SPECIFICATION);
}
List columns = (List) value.getValueAsPojo();
diffReport = dataFileManager.diff(lSource, fTarget);
if (diffReport.size() != 0)
{
dataFileManager.report(diffManager, op, failureId != null ? failureId : synthFailureId, diffReport);
throw new TestAssertionFailure("Table <" + sourceTable + "> does not match <" + operation.getTarget() + ">", failureId != null ? failureId : synthFailureId);
}
}
catch (TestExecutionError e)
{
throw e;
}
catch (TestAssertionFailure e)
{
throw e;
}
catch (Exception e)
{
throw new TestExecutionError("", e);
}
break;
}
case empty:
// for these two, just dump the table to a file and assert file size is or isn't 0
// visit the file, skipping the header.
// if there are any non-blank or non-comment rows then this is a fail
{
String synthFailureId = connMode.connectionId + "." + connMode.getPrettyMode() + "." + qualifiedName;
try
{
DataFile fSource = dataFileManager.loadDataFile(target, ffs);
int lines = 0;
DataFile.FileData fdata = fSource.getFileData();
try
{
Iterator it = fdata.iterator();
while (it.hasNext())
{
it.next();
lines++;
}
}
finally
{
fdata.dispose();
}
if (lines != 0)
{
throw new TestAssertionFailure("Object " + synthFailureId + " not empty", failureId != null ? failureId : synthFailureId);
}
}
catch (IOException e)
{
throw new TestExecutionError("", e);
}
break;
}
case not_empty:
{
String synthFailureId = connMode.connectionId + "." + connMode.getPrettyMode() + "." + qualifiedName;
try
{
DataFile fSource = dataFileManager.loadDataFile(target, ffs);
int lines = 0;
DataFile.FileData fdata = fSource.getFileData();
try
{
Iterator it = fdata.iterator();
while (it.hasNext())
{
it.next();
lines++;
}
}
finally
{
fdata.dispose();
}
if (lines == 0)
{
throw new TestAssertionFailure("Object " + synthFailureId + " is empty", failureId != null ? failureId : synthFailureId);
}
}
catch (IOException e)
{
throw new TestExecutionError("", e);
}
break;
}
}
return ClassResponder.action_code.handled;
}
}