/*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 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.steps.transexecutor;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItem;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.ObjectLocationSpecificationMethod;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.plugins.PluginRegistry;
import org.pentaho.di.core.plugins.StepPluginType;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaString;
import org.pentaho.di.trans.RowProducer;
import org.pentaho.di.trans.RowStepCollector;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransHopMeta;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.steps.dummytrans.DummyTransMeta;
import org.pentaho.di.trans.steps.injector.InjectorMeta;
public class TransExecutorTest {
private static final String SAMPLE_INPUT = "abc";
private static final String EXPECTED_SUBTRANS_OUTPUT_PATTERN = "aa";
private static final int EXPECTED_SUBTRANS_OUTPUT_AMOUNT = 10;
private static final String SUBTRANS_PATH = "testfiles/org/pentaho/di/trans/steps/transexecutor/subtrans.ktr";
@BeforeClass
public static void setUpClass() throws Exception {
KettleEnvironment.init();
}
private PluginRegistry pluginRegistry;
private StepMeta injector;
private StepMeta transExecutor;
private StepMeta dummy;
private TransMeta transMeta;
@Before
public void setUp() throws Exception {
pluginRegistry = PluginRegistry.getInstance();
injector = createInjector( "Injector" );
transExecutor = createExecutor( "Trans Executor" );
dummy = createDummy( "Dummy Output" );
TransExecutorMeta executorMeta = getExecutorMeta( transExecutor );
executorMeta.setFileName( SUBTRANS_PATH );
executorMeta.setSpecificationMethod( ObjectLocationSpecificationMethod.FILENAME );
transMeta = new TransMeta();
transMeta.setName( "transformation executor" );
transMeta.addStep( injector );
transMeta.addStep( transExecutor );
transMeta.addStep( dummy );
// injector -> executor
transMeta.addTransHop( new TransHopMeta( injector, transExecutor ) );
// executor -> dummy
transMeta.addTransHop( new TransHopMeta( transExecutor, dummy ) );
}
private StepMeta createInjector( String stepname ) {
InjectorMeta im = new InjectorMeta();
String injectorPid = pluginRegistry.getPluginId( StepPluginType.class, im );
return new StepMeta( injectorPid, stepname, im );
}
private StepMeta createExecutor( String stepname ) {
TransExecutorMeta transExecutorMeta = new TransExecutorMeta();
String transExecutorPID = pluginRegistry.getPluginId( StepPluginType.class, transExecutorMeta );
return new StepMeta( transExecutorPID, stepname, transExecutorMeta );
}
private static TransExecutorMeta getExecutorMeta( StepMeta stepMeta ) {
return (TransExecutorMeta) stepMeta.getStepMetaInterface();
}
private StepMeta createDummy( String stepname ) {
DummyTransMeta dummyTransMeta = new DummyTransMeta();
String dummyStepPID = pluginRegistry.getPluginId( StepPluginType.class, dummyTransMeta );
return new StepMeta( dummyStepPID, stepname, dummyTransMeta );
}
@Test
public void subTransOutputIsAccessibleOutside() throws Exception {
TransExecutorMeta executorMeta = getExecutorMeta( transExecutor );
executorMeta.setOutputRowsSourceStepMeta( dummy );
Trans trans = createTrans( transMeta );
RowStepCollector endRc = listenExecutor( trans );
RowProducer rp = trans.addRowProducer( injector.getName(), 0 );
trans.startThreads();
RowMetaAndData testInput = new RowMetaAndData( createRowMetaForOneField(), SAMPLE_INPUT );
rp.putRow( testInput.getRowMeta(), testInput.getData() );
rp.finished();
trans.waitUntilFinished();
assertEquals( EXPECTED_SUBTRANS_OUTPUT_AMOUNT, endRc.getRowsWritten().size() );
assertThat( asList( endRc.getRowsWritten().get( 0 ).getData() ),
hasItem( (Object) EXPECTED_SUBTRANS_OUTPUT_PATTERN )
);
}
private static Trans createTrans( TransMeta transMeta ) throws Exception {
Trans trans = new Trans( transMeta );
trans.prepareExecution( null );
return trans;
}
private RowStepCollector listenExecutor( Trans trans ) {
StepInterface transExecutorStep = trans.getStepInterface( transExecutor.getName(), 0 );
RowStepCollector rc = new RowStepCollector();
transExecutorStep.addRowListener( rc );
return rc;
}
private static RowMetaInterface createRowMetaForOneField() {
RowMetaInterface rm = new RowMeta();
ValueMetaInterface[] valuesMeta = { new ValueMetaString( "field1" ), };
for ( ValueMetaInterface aValuesMeta : valuesMeta ) {
rm.addValueMeta( aValuesMeta );
}
return rm;
}
@Test
public void executorsInputIsStraightlyCopiedToOutput() throws Exception {
TransExecutorMeta executorMeta = getExecutorMeta( transExecutor );
executorMeta.setExecutorsOutputStepMeta( dummy );
Trans trans = createTrans( transMeta );
RowStepCollector endRc = listenExecutor( trans );
RowProducer rp = trans.addRowProducer( injector.getName(), 0 );
trans.startThreads();
RowMetaAndData testInput = new RowMetaAndData( createRowMetaForOneField(), SAMPLE_INPUT );
rp.putRow( testInput.getRowMeta(), testInput.getData() );
rp.finished();
trans.waitUntilFinished();
assertEquals( testInput.size(), endRc.getRowsWritten().size() );
assertThat( asList( endRc.getRowsWritten().get( 0 ).getData() ),
hasItem( (Object) SAMPLE_INPUT )
);
}
@Test
public void subTransExecutionStatisticsIsCollected() throws Exception {
TransExecutorMeta executorMeta = getExecutorMeta( transExecutor );
executorMeta.setExecutionTimeField( "time" );
executorMeta.setExecutionResultTargetStepMeta( dummy );
Trans trans = createTrans( transMeta );
RowStepCollector endRc = listenExecutor( trans );
RowProducer rp = trans.addRowProducer( injector.getName(), 0 );
trans.startThreads();
RowMetaAndData testInput = new RowMetaAndData( createRowMetaForOneField(), SAMPLE_INPUT );
rp.putRow( testInput.getRowMeta(), testInput.getData() );
rp.finished();
trans.waitUntilFinished();
assertFalse( endRc.getRowsWritten().isEmpty() );
// execution time field
assertNotNull( endRc.getRowsWritten().get( 0 ).getData()[ 0 ] );
}
}