/*! ****************************************************************************** * * 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 junit.framework.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.pentaho.di.core.exception.KettleValueException; import org.pentaho.di.core.logging.LoggingObjectInterface; 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.ValueMetaString; import org.pentaho.di.trans.steps.mock.StepMockHelper; import java.util.Arrays; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; public class GroupByNullInputTest { public static final int NUMBER_OF_COLUMNS = 1; public static final String ANY_FIELD_NAME = "anyFieldName"; static StepMockHelper<GroupByMeta, GroupByData> mockHelper; private GroupBy step; private GroupByData groupByStepData; private GroupByMeta groupByStepMeta; private RowMetaInterface rowMetaInterfaceMock; @BeforeClass public static void setUpBeforeClass() 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 ); } @Before public void setUp() throws Exception { groupByStepData = new GroupByData(); groupByStepMeta = new GroupByMeta(); when( mockHelper.stepMeta.getStepMetaInterface() ).thenReturn( groupByStepMeta ); rowMetaInterfaceMock = Mockito.mock( RowMetaInterface.class ); groupByStepData.inputRowMeta = rowMetaInterfaceMock; groupByStepData.aggMeta = rowMetaInterfaceMock; step = new GroupBy( mockHelper.stepMeta, groupByStepData, 0, mockHelper.transMeta, mockHelper.trans ); } private void setAggregationTypesAndInitData( int[] aggregationTypes ) { //types of aggregation functions int countOfAggregations = aggregationTypes.length; groupByStepData.subjectnrs = new int[ countOfAggregations ]; System.arraycopy( aggregationTypes, 0, groupByStepData.subjectnrs, 0, countOfAggregations ); groupByStepMeta.setAggregateType( aggregationTypes ); //init field names for aggregation columns String[] fieldNames = new String[ countOfAggregations ]; Arrays.fill( fieldNames, ANY_FIELD_NAME ); groupByStepMeta.setAggregateField( fieldNames ); groupByStepData.subjectnrs = new int[ countOfAggregations ]; //init sum arrays which are set on processRow which is not always called from tests groupByStepData.previousSums = new Object[ countOfAggregations ]; groupByStepData.counts = new long[ countOfAggregations ]; groupByStepData.previousAvgCount = new long[ countOfAggregations ]; groupByStepData.previousAvgSum = new Object[ countOfAggregations ]; Arrays.fill( groupByStepData.previousSums, 0 ); Arrays.fill( groupByStepData.previousAvgCount, 0 ); Arrays.fill( groupByStepData.previousAvgSum, 0 ); } /** * PMD-1037 NPE error appears when user uses "Data Profile" feature to some tables in Hive 2. */ @Test public void testNullInputDataForStandardDeviation() throws KettleValueException { setAggregationTypesAndInitData( new int[] { 15 } ); ValueMetaInterface vmi = new ValueMetaInteger(); when( rowMetaInterfaceMock.getValueMeta( Mockito.anyInt() ) ).thenReturn( vmi ); Object[] row1 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row1, null ); step.newAggregate( row1 ); step.calcAggregate( row1 ); Object[] aggregateResult = step.getAggregateResult(); Assert.assertNull( "Returns null if aggregation is null", aggregateResult[0] ); } @Test public void testNullInputDataForAggregationWithNumbers() throws KettleValueException { setAggregationTypesAndInitData( new int[] { 1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15 } ); ValueMetaInterface vmi = new ValueMetaInteger(); when( rowMetaInterfaceMock.getValueMeta( Mockito.anyInt() ) ).thenReturn( vmi ); Object[] row1 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row1, null ); step.newAggregate( row1 ); step.calcAggregate( row1 ); Object[] aggregateResult = step.getAggregateResult(); Assert.assertNull( "Returns null if aggregation is null", aggregateResult[0] ); } @Test public void testNullInputDataForAggregationWithNumbersMedianFunction() throws KettleValueException { setAggregationTypesAndInitData( new int[] { 3, 4 } ); ValueMetaInterface vmi = new ValueMetaInteger(); when( rowMetaInterfaceMock.getValueMeta( Mockito.anyInt() ) ).thenReturn( vmi ); //PERCENTILE set groupByStepMeta.setValueField( new String[] { "3", "3" } ); Object[] row1 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row1, null ); step.newAggregate( row1 ); step.calcAggregate( row1 ); step.getAggregateResult(); } @Test public void testNullInputDataForAggregationWithStrings() throws KettleValueException { setAggregationTypesAndInitData( new int[] { 8, 16, 17, 18 } ); groupByStepMeta.setValueField( new String[] { "," } ); groupByStepMeta.setSubjectField( new String[] { ANY_FIELD_NAME, ANY_FIELD_NAME } ); ValueMetaInterface vmi = new ValueMetaString(); when( rowMetaInterfaceMock.getValueMeta( Mockito.anyInt() ) ).thenReturn( vmi ); Object[] row1 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row1, null ); step.newAggregate( row1 ); step.calcAggregate( row1 ); Object[] row2 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row2, null ); step.calcAggregate( row2 ); Object[] row3 = new Object[ NUMBER_OF_COLUMNS ]; Arrays.fill( row3, null ); step.calcAggregate( row3 ); step.getAggregateResult(); } }