/*! ****************************************************************************** * * 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.groupby; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.vfs2.FileSystemException; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.pentaho.di.core.BlockingRowSet; import org.pentaho.di.core.RowSet; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettlePluginException; import org.pentaho.di.core.logging.LoggingObjectInterface; 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.ValueMetaInteger; import org.pentaho.di.core.row.value.ValueMetaPluginType; import org.pentaho.di.core.row.value.ValueMetaString; import org.pentaho.di.core.variables.Variables; import org.pentaho.di.repository.Repository; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; import org.pentaho.di.trans.steps.mock.StepMockHelper; import org.pentaho.metastore.api.IMetaStore; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class GroupByTest { private StepMockHelper<GroupByMeta, GroupByData> mockHelper; @BeforeClass public static void setUpBeforeClass() throws KettlePluginException { ValueMetaPluginType.getInstance().searchPlugins(); } @Before public void setUp() throws Exception { mockHelper = new StepMockHelper<>( "Group By", GroupByMeta.class, GroupByData.class ); when( mockHelper.logChannelInterfaceFactory.create( any(), any( LoggingObjectInterface.class ) ) ).thenReturn( mockHelper.logChannelInterface ); when( mockHelper.trans.isRunning() ).thenReturn( true ); } @After public void tearDown() throws Exception { mockHelper.cleanUp(); } @Test public void testProcessRow() throws KettleException { GroupByMeta groupByMeta = mock( GroupByMeta.class ); GroupByData groupByData = mock( GroupByData.class ); GroupBy groupBySpy = Mockito.spy( new GroupBy( mockHelper.stepMeta, mockHelper.stepDataInterface, 0, mockHelper.transMeta, mockHelper.trans ) ); doReturn( null ).when( groupBySpy ).getRow(); doReturn( null ).when( groupBySpy ).getInputRowMeta(); RowMetaInterface rowMeta = new RowMeta(); rowMeta.addValueMeta( new ValueMetaInteger( "ROWNR" ) ); List<RowSet> outputRowSets = new ArrayList<RowSet>(); BlockingRowSet rowSet = new BlockingRowSet( 1 ); rowSet.putRow( rowMeta, new Object[] { new Long( 0 ) } ); outputRowSets.add( rowSet ); groupBySpy.setOutputRowSets( outputRowSets ); final String[] sub = { "b" }; doReturn( sub ).when( groupByMeta ).getSubjectField(); final String[] groupField = { "a" }; doReturn( groupField ).when( groupByMeta ).getGroupField(); final String[] aggFields = { "b_g" }; doReturn( aggFields ).when( groupByMeta ).getAggregateField(); final int[] aggType = { GroupByMeta.TYPE_GROUP_CONCAT_COMMA }; doReturn( aggType ).when( groupByMeta ).getAggregateType(); when( mockHelper.transMeta.getPrevStepFields( mockHelper.stepMeta ) ).thenReturn( new RowMeta() ); groupBySpy.processRow( groupByMeta, groupByData ); assertTrue( groupBySpy.getOutputRowSets().get( 0 ).isDone() ); } @Test public void testGetFields() { RowMeta outputFields = new RowMeta(); outputFields.addValueMeta( new ValueMetaString( "group_by_field" ) ); outputFields.addValueMeta( new ValueMetaInteger( "raw_integer" ) ); outputFields.addValueMeta( new ValueMetaString( "raw_string" ) ); GroupByMeta meta = new GroupByMeta(); meta.allocate( 1, 8 ); meta.setGroupField( new String[]{ "group_by_field" } ); meta.setAggregateField( new String[]{ "perc_field", "stddev_field", "median_field", "count_distinct_field", "count_any_field", "count_all_field", "concat_comma_field", "concat_custom_field" } ); meta.setSubjectField( new String[]{ "raw_integer", "raw_integer", "raw_integer", "raw_integer", "raw_integer", "raw_integer", "raw_string", "raw_string" } ); meta.setAggregateType( new int[] { GroupByMeta.TYPE_GROUP_PERCENTILE, GroupByMeta.TYPE_GROUP_STANDARD_DEVIATION, GroupByMeta.TYPE_GROUP_MEDIAN, GroupByMeta.TYPE_GROUP_COUNT_DISTINCT, GroupByMeta.TYPE_GROUP_COUNT_ANY, GroupByMeta.TYPE_GROUP_COUNT_ALL, GroupByMeta.TYPE_GROUP_CONCAT_COMMA, GroupByMeta.TYPE_GROUP_CONCAT_STRING } ); meta.getFields( outputFields, "Group By Step", (RowMetaInterface[]) null, (StepMeta) null, (Variables) null, (Repository) null, (IMetaStore) null ); assertEquals( outputFields.getValueMetaList().size(), 9 ); assertTrue( outputFields.getValueMeta( 0 ).getType() == ValueMetaInterface.TYPE_STRING ); assertTrue( outputFields.getValueMeta( 0 ).getName().equals( "group_by_field" ) ); assertTrue( outputFields.getValueMeta( 1 ).getType() == ValueMetaInterface.TYPE_NUMBER ); assertTrue( outputFields.getValueMeta( 1 ).getName().equals( "perc_field" ) ); assertTrue( outputFields.getValueMeta( 2 ).getType() == ValueMetaInterface.TYPE_NUMBER ); assertTrue( outputFields.getValueMeta( 2 ).getName().equals( "stddev_field" ) ); assertTrue( outputFields.getValueMeta( 3 ).getType() == ValueMetaInterface.TYPE_NUMBER ); assertTrue( outputFields.getValueMeta( 3 ).getName().equals( "median_field" ) ); assertTrue( outputFields.getValueMeta( 4 ).getType() == ValueMetaInterface.TYPE_INTEGER ); assertTrue( outputFields.getValueMeta( 4 ).getName().equals( "count_distinct_field" ) ); assertTrue( outputFields.getValueMeta( 5 ).getType() == ValueMetaInterface.TYPE_INTEGER ); assertTrue( outputFields.getValueMeta( 5 ).getName().equals( "count_any_field" ) ); assertTrue( outputFields.getValueMeta( 6 ).getType() == ValueMetaInterface.TYPE_INTEGER ); assertTrue( outputFields.getValueMeta( 6 ).getName().equals( "count_all_field" ) ); assertTrue( outputFields.getValueMeta( 7 ).getType() == ValueMetaInterface.TYPE_STRING ); assertTrue( outputFields.getValueMeta( 7 ).getName().equals( "concat_comma_field" ) ); assertTrue( outputFields.getValueMeta( 8 ).getType() == ValueMetaInterface.TYPE_STRING ); assertTrue( outputFields.getValueMeta( 8 ).getName().equals( "concat_custom_field" ) ); } @Test public void testTempFileIsDeleted_AfterCallingDisposeMethod() throws Exception { GroupByData groupByData = new GroupByData(); groupByData.tempFile = File.createTempFile( "test", ".txt" ); // emulate connections to file are opened groupByData.fosToTempFile = new FileOutputStream( groupByData.tempFile ); groupByData.fisToTmpFile = new FileInputStream( groupByData.tempFile ); GroupBy groupBySpy = Mockito.spy( new GroupBy( mockHelper.stepMeta, groupByData, 0, mockHelper.transMeta, mockHelper.trans ) ); assertTrue( groupByData.tempFile.exists() ); groupBySpy.dispose( mock( StepMetaInterface.class ), groupByData ); // check file is deleted assertFalse( groupByData.tempFile.exists() ); } @Test public void testAddToBuffer() throws KettleException, FileSystemException { GroupByData groupByData = new GroupByData(); ArrayList listMock = mock( ArrayList.class ); when( listMock.size() ).thenReturn( 5001 ); groupByData.bufferList = listMock; groupByData.rowsOnFile = 0; RowMetaInterface inputRowMetaMock = mock( RowMetaInterface.class ); groupByData.inputRowMeta = inputRowMetaMock; GroupBy groupBySpy = Mockito.spy( new GroupBy( mockHelper.stepMeta, groupByData, 0, mockHelper.transMeta, mockHelper.trans ) ); GroupByMeta groupByMetaMock = mock( GroupByMeta.class ); when( groupByMetaMock.getPrefix() ).thenReturn( "group-by-test-temp-file-" ); when( groupBySpy.getMeta() ).thenReturn( groupByMetaMock ); String userDir = System.getProperty( "user.dir" ); String vfsFilePath = "file:///" + userDir; when( groupBySpy.environmentSubstitute( anyString() ) ).thenReturn( vfsFilePath ); Object[] row = { "abc" }; // tested method itself groupBySpy.addToBuffer( row ); // check if file is created assertTrue( groupByData.tempFile.exists() ); groupBySpy.dispose( groupByMetaMock, groupByData ); // check file is deleted assertFalse( groupByData.tempFile.exists() ); // since path started with "file:///" verify( groupBySpy, times( 1 ) ).retrieveVfsPath( anyString() ); } }