/*! ******************************************************************************
*
* 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.joinrows;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.BlockingRowSet;
import org.pentaho.di.core.RowSet;
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.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaString;
import org.pentaho.di.trans.RowStepCollector;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
/**
* @author Denis Mashukov
*/
public class JoinRowsTest {
private StepMetaInterface meta;
private JoinRowsData data;
@Before
public void setUp() throws Exception {
meta = new JoinRowsMeta();
data = new JoinRowsData();
}
@After
public void tearDown() {
meta = null;
data = null;
}
/**
* BACKLOG-8520 Check that method call does't throw an error NullPointerException.
*/
@Test
public void checkThatMethodPerformedWithoutError() throws Exception {
getJoinRows().dispose( meta, data );
}
@Test
public void disposeDataFiles() throws Exception {
File mockFile1 = mock( File.class );
File mockFile2 = mock( File.class );
data.file = new File[] {null, mockFile1, mockFile2};
getJoinRows().dispose( meta, data );
verify( mockFile1, times( 1 ) ).delete();
verify( mockFile2, times( 1 ) ).delete();
}
private JoinRows getJoinRows() throws Exception {
StepMeta stepMeta = new StepMeta();
TransMeta transMeta = new TransMeta();
Trans trans = new Trans( transMeta );
transMeta.clear();
transMeta.addStep( stepMeta );
transMeta.setStep( 0, stepMeta );
stepMeta.setName( "test" );
trans.setLog( mock( LogChannelInterface.class ) );
trans.prepareExecution( null );
trans.startThreads();
return new JoinRows( stepMeta, null, 0, transMeta, trans );
}
@Test
public void testJoinRowsStep() throws Exception {
JoinRowsMeta joinRowsMeta = new JoinRowsMeta();
joinRowsMeta.setMainStepname( "main step name" );
joinRowsMeta.setPrefix( "out" );
joinRowsMeta.setCacheSize( 3 );
JoinRowsData joinRowsData = new JoinRowsData();
JoinRows joinRows = getJoinRows();
joinRows.getTrans().setRunning( true );
joinRows.init( joinRowsMeta, joinRowsData );
List<RowSet> rowSets = new ArrayList<>();
rowSets.add( getRowSetWithData( 3, "main --", true ) );
rowSets.add( getRowSetWithData( 3, "secondary --", false ) );
joinRows.setInputRowSets( rowSets );
RowStepCollector rowStepCollector = new RowStepCollector();
joinRows.addRowListener( rowStepCollector );
joinRows.getLogChannel().setLogLevel( LogLevel.ROWLEVEL );
KettleLogStore.init();
while ( true ) {
if ( !joinRows.processRow( joinRowsMeta, joinRowsData ) ) {
break;
}
}
rowStepCollector.getRowsWritten();
//since we have data join of two row sets with size 3 then we must have 9 written rows
assertEquals( 9, rowStepCollector.getRowsWritten().size() );
assertEquals( 6, rowStepCollector.getRowsRead().size() );
Object[][] expectedResult = createExpectedResult();
List<Object[]> rowWritten = rowStepCollector.getRowsWritten().stream().map( RowMetaAndData::getData ).collect( Collectors.toList() );
for ( int i = 0; i < 9; i++ ) {
assertTrue( Arrays.equals( expectedResult[i], rowWritten.get( i ) ) );
}
}
BlockingRowSet getRowSetWithData( int size, String dataPrefix, boolean isMainStep ) {
BlockingRowSet blockingRowSet = new BlockingRowSet( size );
RowMeta rowMeta = new RowMeta();
ValueMetaInterface valueMetaString = new ValueMetaString( dataPrefix + " first value name" );
ValueMetaInterface valueMetaInteger = new ValueMetaString( dataPrefix + " second value name" );
ValueMetaInterface valueMetaBoolean = new ValueMetaString( dataPrefix + " third value name" );
rowMeta.addValueMeta( valueMetaString );
rowMeta.addValueMeta( valueMetaInteger );
rowMeta.addValueMeta( valueMetaBoolean );
blockingRowSet.setRowMeta( rowMeta );
for ( int i = 0; i < size; i++ ) {
Object[] rowData = new Object[3];
rowData[0] = dataPrefix + " row[" + i + "]-first value";
rowData[1] = dataPrefix + " row[" + i + "]-second value";
rowData[2] = dataPrefix + " row[" + i + "]-third value";
blockingRowSet.putRow( rowMeta, rowData );
}
if ( isMainStep ) {
blockingRowSet.setThreadNameFromToCopy( "main step name", 0, null, 0 );
} else {
blockingRowSet.setThreadNameFromToCopy( "secondary step name", 0, null, 0 );
}
blockingRowSet.setDone();
return blockingRowSet;
}
private Object[][] createExpectedResult() {
Object[][] objects = {{"main -- row[0]-first value", "main -- row[0]-second value", "main -- row[0]-third value", "secondary -- row[0]-first value", "secondary -- row[0]-second value", "secondary -- row[0]-third value"},
{"main -- row[0]-first value", "main -- row[0]-second value", "main -- row[0]-third value", "secondary -- row[1]-first value", "secondary -- row[1]-second value", "secondary -- row[1]-third value"},
{"main -- row[0]-first value", "main -- row[0]-second value", "main -- row[0]-third value", "secondary -- row[2]-first value", "secondary -- row[2]-second value", "secondary -- row[2]-third value"},
{"main -- row[1]-first value", "main -- row[1]-second value", "main -- row[1]-third value", "secondary -- row[0]-first value", "secondary -- row[0]-second value", "secondary -- row[0]-third value"},
{"main -- row[1]-first value", "main -- row[1]-second value", "main -- row[1]-third value", "secondary -- row[1]-first value", "secondary -- row[1]-second value", "secondary -- row[1]-third value"},
{"main -- row[1]-first value", "main -- row[1]-second value", "main -- row[1]-third value", "secondary -- row[2]-first value", "secondary -- row[2]-second value", "secondary -- row[2]-third value"},
{"main -- row[2]-first value", "main -- row[2]-second value", "main -- row[2]-third value", "secondary -- row[0]-first value", "secondary -- row[0]-second value", "secondary -- row[0]-third value"},
{"main -- row[2]-first value", "main -- row[2]-second value", "main -- row[2]-third value", "secondary -- row[1]-first value", "secondary -- row[1]-second value", "secondary -- row[1]-third value"},
{"main -- row[2]-first value", "main -- row[2]-second value", "main -- row[2]-third value", "secondary -- row[2]-first value", "secondary -- row[2]-second value", "secondary -- row[2]-third value"}};
return objects;
}
}