/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* 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.pentaho.di.trans;
import java.util.concurrent.atomic.AtomicBoolean;
import junit.framework.TestCase;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.logging.KettleLogStore;
import org.pentaho.di.core.logging.LogLevel;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.RowAdapter;
import org.pentaho.di.trans.step.StepInterface;
public class NormalExecutionTest extends TestCase {
private boolean initCalled = false;
protected synchronized void setUp() throws Exception {
if ( initCalled ) {
return;
}
KettleEnvironment.init();
initCalled = true;
KettleLogStore.getAppender().setMaxNrLines( 100 );
}
/**
* Mock {@link org.pentaho.di.trans.step.RowListener} that totals the number of events.
* Can be stopped with {@code close()}.
*/
protected class CountingRowListener extends RowAdapter {
private Long error;
private Long written;
private Long read;
private Long ignoredError;
private Long ignoredWritten;
private Long ignoredRead;
private AtomicBoolean listening;
/**
* Creates a new counting row listener that is listening.
*/
public CountingRowListener() {
ignoredError = ignoredWritten = ignoredRead = error = written = read = 0L;
listening = new AtomicBoolean( true );
}
public void setListening( final boolean b ) {
listening.set( b );
}
public boolean isListening() {
return listening.get();
}
/**
* @return The number of {@code errorRowWrittenEvent()} calls while {@code listening == true}
*/
public Long getError() {
return error;
}
/**
* @return The number of {@code rowWrittenEvent()} calls while {@code listening == true}
*/
public Long getWritten() {
return written;
}
/**
* @return The number of {@code rowReadEvent()} calls while {@code listening == true}
*/
public Long getRead() {
return read;
}
/**
* @return The number of {@code errorRowWrittenEvent()} calls while {@code listening == false}
*/
public Long getIgnoredError() {
return ignoredError;
}
/**
* @return The number of {@code rowWrittenEvent()} calls while {@code listening == false}
*/
public Long getIgnoredWritten() {
return ignoredWritten;
}
/**
* @return The number of {@code rowReadEvent()} calls while {@code listening == false}
*/
public Long getIgnoredRead() {
return ignoredRead;
}
@Override
public void errorRowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
if ( !isListening() ) {
ignoredError++;
} else {
error++;
}
}
@Override
public void rowReadEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
if ( !isListening() ) {
ignoredRead++;
} else {
read++;
}
}
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
if ( !isListening() ) {
ignoredWritten++;
} else {
written++;
}
}
}
/**
* Tests that all rows are written out to {@link org.pentaho.di.trans.step.RowListener}s
* before {@link Trans#waitUntilFinished} returns.
*/
public void testWaitUntilFinished() throws Exception {
// The number of rows we'll pump through our RowProducer.
final Long ROWS = 10L;
final int ITERATIONS = 100;
// Load transformation
TransMeta transMeta = new TransMeta( "testfiles/NormalExecutionTest - WaitUntilFinished.ktr" );
transMeta.setSizeRowset( 5 );
for ( int t = 0; t < ITERATIONS; t++ ) {
Trans trans = new Trans( transMeta );
trans.setLogLevel( LogLevel.NOTHING );
trans.prepareExecution( null );
StepInterface injector = trans.findRunThread( "Injector" );
StepInterface output = trans.findRunThread( "Output" );
// Get the RowMeta for the injector step (it will be an Integer named 'a' of length 1)
RowMeta injectorRowMeta = new RowMeta();
( (BaseStepMeta) injector.getStepMeta().getStepMetaInterface() ).getFields(
injectorRowMeta, null, null, null, null, null, null );
RowProducer producer = trans.addRowProducer( injector.getStepname(), 0 );
// Our counting row listener will record how many rows we receive
CountingRowListener countingListener = new CountingRowListener();
output.addRowListener( countingListener );
// Feed input to transformation
Object[] row = new Object[1];
trans.startThreads();
for ( Integer i = 0; i < ROWS; i++ ) {
row[0] = i;
producer.putRow( injectorRowMeta, row );
}
producer.finished();
trans.waitUntilFinished(); // This should block until everything is complete
countingListener.setListening( false );
assertTrue( trans.isFinished() );
/*
*
* // Make sure we collect all output so we can report how long it actually took long start =
* System.currentTimeMillis(); while (countingListener.getWritten() + countingListener.getIgnoredWritten() !=
* ROWS) { Thread.sleep(0, 10); } long end = System.currentTimeMillis();
*
* System.out.println("Run report for RowListener on last step in transformation, iteration #"+(t+1)+" :\n");
* System.out.println("Rows read : " + countingListener.getRead());
* System.out.println("Rows written : " + countingListener.getWritten());
* System.out.println("Rows error : " + countingListener.getError());
* System.out.println("Rows ignored (read) : " + countingListener.getIgnoredRead());
* System.out.println("Rows ignored (written): " + countingListener.getIgnoredWritten());
* System.out.println("Rows ignored (error) : " + countingListener.getIgnoredError());
* System.out.println("Had to wait " + (end - start) + "ms for all data to be received by the row listener.");
*/
assertEquals( "Incorrect number of read rows received", ROWS, countingListener.getRead() );
assertEquals( "Incorrect number of written rows received", ROWS, countingListener.getWritten() );
assertEquals( "Incorrect number of error rows received", new Long( 0 ), countingListener.getError() );
}
}
/*
* public void testStartThreads_only_one_TransListener() throws Exception { TransMeta transMeta = new
* TransMeta("testfiles/NormalExecutionTest - WaitUntilFinished.ktr");
*
* Trans trans = new Trans(transMeta); trans.setLogLevel(LogLevel.NOTHING);
*
* trans.prepareExecution(null); trans.startThreads(); trans.waitUntilFinished();
*
* // Record original number of trans listeners int numTransListeners = trans.getTransListeners().size();
*
* trans.prepareExecution(null); trans.startThreads(); trans.waitUntilFinished();
*
* assertEquals("TransListeners on Trans are growing", numTransListeners, trans.getTransListeners().size()); }
*/
}