/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2015 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.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.pentaho.di.core.Const; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.RowMetaAndData; import org.pentaho.di.core.exception.KettleException; 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.ValueMetaBigNumber; import org.pentaho.di.core.row.value.ValueMetaInteger; import org.pentaho.di.core.row.value.ValueMetaNumber; import org.pentaho.di.core.row.value.ValueMetaString; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.TransTestFactory; /** * 'Int' is added just to avoid name conflicts with engine/test_src existing class. * */ public class GroupByIntTest { public static final String stepName = "GroupBY"; public static final String KEY1 = "s1"; public static final String KEY2 = "i2"; public static final String KEY3 = "n3"; public static final String KEY4 = "bn4"; public static final String OUT1 = "out1"; public static final String OUT2 = "out2"; public static final String OUT3 = "out3"; public static final String OUT4 = "out4"; @BeforeClass public static void before() throws KettleException { KettleEnvironment.init(); } List<RowMetaAndData> getTestRowMetaAndData( int count, Integer[] nulls ) { List<RowMetaAndData> list = new ArrayList<RowMetaAndData>(); RowMetaInterface rm = new RowMeta(); rm.addValueMeta( new ValueMetaString( KEY1 ) ); rm.addValueMeta( new ValueMetaInteger( KEY2 ) ); rm.addValueMeta( new ValueMetaNumber( KEY3 ) ); rm.addValueMeta( new ValueMetaBigNumber( KEY4 ) ); Object[] row = new Object[4]; List<Integer> nullsList = Arrays.asList( nulls ); for ( int i = 0; i < count; i++ ) { if ( nullsList.contains( i ) ) { for ( int j = 0; j < row.length; j++ ) { row[j] = null; } } else { row[0] = ""; row[1] = 1L; row[2] = 2.0; row[3] = new BigDecimal( 3 ); } list.add( new RowMetaAndData( rm, row ) ); } return list; } /** * Since of PDI-10250 fix we replace null value with 0 representation. But not all 0 is the same. * We must be correct if it is 0L, or it is double 0, or it is BigDecimal 0. * Not keep attention to java class conversions we can get specific errors on UI :( * * * @throws KettleException */ @Test public void testGroupByNullAggregationsConversion() throws KettleException { // this to force null aggregations becomes nulls System.getProperties().setProperty( Const.KETTLE_AGGREGATION_ALL_NULLS_ARE_ZERO, "Y" ); GroupByMeta meta = new GroupByMeta(); meta.setSubjectField( new String[] { KEY1, KEY2, KEY3, KEY4 } ); meta.setAggregateField( new String[] { OUT1, OUT2, OUT3, OUT4 } ); meta.setGroupField( new String[] { KEY1 } ); meta.setAggregateType( new int[] { GroupByMeta.TYPE_GROUP_CONCAT_COMMA, GroupByMeta.TYPE_GROUP_SUM, GroupByMeta.TYPE_GROUP_SUM, GroupByMeta.TYPE_GROUP_SUM } ); TransMeta transMeta = TransTestFactory.generateTestTransformation( null, meta, stepName ); List<RowMetaAndData> inputList = getTestRowMetaAndData( 2, new Integer[] { 0, 1 } ); List<RowMetaAndData> ret = TransTestFactory.executeTestTransformation( transMeta, TransTestFactory.INJECTOR_STEPNAME, stepName, TransTestFactory.DUMMY_STEPNAME, inputList ); Assert.assertNotNull( "At least it is not null", ret ); Assert.assertEquals( "Ouput is just one row", 1, ret.size() ); RowMetaAndData rmd = ret.get( 0 ); // now take a closer look at value meta types we do have at the end: ValueMetaInterface vmi = rmd.getValueMeta( 0 ); Assert.assertEquals( "First is usually is grouping field", ValueMetaInterface.TYPE_STRING, vmi.getType() ); Assert.assertEquals( "This is key1 field", KEY1, vmi.getName() ); vmi = rmd.getValueMeta( 1 ); Assert.assertEquals( "The next value is first aggregation", OUT1, vmi.getName() ); Assert.assertEquals( "Since it was null String output will be empty string", "", rmd.getData()[1] ); vmi = rmd.getValueMeta( 2 ); Assert.assertEquals( "Third field is second output field", OUT2, vmi.getName() ); Assert.assertEquals( "To keep correct conversion it must be Long object (Integer representation)", 0L, rmd .getData()[2] ); vmi = rmd.getValueMeta( 3 ); Assert.assertEquals( "4 is 3 output field", OUT3, vmi.getName() ); Assert.assertEquals( "And since it was null it become correct 0", 0.0, rmd.getData()[3] ); vmi = rmd.getValueMeta( 4 ); Assert.assertEquals( "And the last one is null which becomes 0 BigNumber", new BigDecimal( 0 ), rmd.getData()[4] ); } }