/*! ******************************************************************************
*
* 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.calculator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import org.junit.AfterClass;
import org.junit.Before;
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.RowSet;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
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.ValueDataUtil;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaInteger;
import org.pentaho.di.core.row.value.ValueMetaNumber;
import org.pentaho.di.trans.step.RowAdapter;
import org.pentaho.di.trans.steps.mock.StepMockHelper;
/**
* Unit tests for calculator step
*
* @author Pavel Sakun
* @see Calculator
*/
public class CalculatorBackwardCompatibilityUnitTest {
private StepMockHelper<CalculatorMeta, CalculatorData> smh;
private static final String SYS_PROPERTY_ROUND_2_MODE = "ROUND_2_MODE";
private static final int OBSOLETE_ROUND_2_MODE = BigDecimal.ROUND_HALF_EVEN;
private static final int DEFAULT_ROUND_2_MODE = Const.ROUND_HALF_CEILING;
/**
* Get value of private static field ValueDataUtil.ROUND_2_MODE.
*
* @return
*/
private static int getRound2Mode() {
int value = -1;
try {
Class<ValueDataUtil> cls = ValueDataUtil.class;
Field f = cls.getDeclaredField( SYS_PROPERTY_ROUND_2_MODE );
f.setAccessible( true );
value = (Integer) f.get( null );
f.setAccessible( false );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
return value;
}
/**
* Set new value of value of private static field ValueDataUtil.ROUND_2_MODE.
*
* @param newValue
*/
private static void setRound2Mode( int newValue ) {
try {
Class<ValueDataUtil> cls = ValueDataUtil.class;
Field f = cls.getDeclaredField( SYS_PROPERTY_ROUND_2_MODE );
f.setAccessible( true );
f.set( null, newValue );
f.setAccessible( false );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
@BeforeClass
public static void init() throws KettleException {
assertEquals( DEFAULT_ROUND_2_MODE, getRound2Mode() );
setRound2Mode( OBSOLETE_ROUND_2_MODE );
assertEquals( OBSOLETE_ROUND_2_MODE, getRound2Mode() );
KettleEnvironment.init( false );
}
@AfterClass
public static void restore() throws Exception {
setRound2Mode( DEFAULT_ROUND_2_MODE );
assertEquals( DEFAULT_ROUND_2_MODE, getRound2Mode() );
}
@Before
public void setUp() {
smh =
new StepMockHelper<CalculatorMeta, CalculatorData>( "Calculator", CalculatorMeta.class,
CalculatorData.class );
when( smh.logChannelInterfaceFactory.create( any(), any( LoggingObjectInterface.class ) ) ).thenReturn(
smh.logChannelInterface );
when( smh.trans.isRunning() ).thenReturn( true );
}
@Test
public void testRound() throws KettleException {
assertRound( 1.0, 1.2 );
assertRound( 2.0, 1.5 );
assertRound( 2.0, 1.7 );
assertRound( 2.0, 2.2 );
assertRound( 3.0, 2.5 );
assertRound( 3.0, 2.7 );
assertRound( -1.0, -1.2 );
assertRound( -1.0, -1.5 );
assertRound( -2.0, -1.7 );
assertRound( -2.0, -2.2 );
assertRound( -2.0, -2.5 );
assertRound( -3.0, -2.7 );
}
public void assertRound( final double expectedResult, final double value ) throws KettleException {
RowMeta inputRowMeta = new RowMeta();
ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" );
inputRowMeta.addValueMeta( valueMeta );
;
RowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value } );
inputRowSet.setRowMeta( inputRowMeta );
Calculator calculator = new Calculator( smh.stepMeta, smh.stepDataInterface, 0, smh.transMeta, smh.trans );
calculator.getInputRowSets().add( inputRowSet );
calculator.setInputRowMeta( inputRowMeta );
calculator.init( smh.initStepMetaInterface, smh.initStepDataInterface );
CalculatorMeta meta = new CalculatorMeta();
meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test",
CalculatorMetaFunction.CALC_ROUND_1, "Value", null, null, ValueMetaInterface.TYPE_NUMBER, 2, 0, false, "", "",
"", "" ) } );
// Verify output
try {
calculator.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
assertEquals( expectedResult, row[1] );
}
} );
calculator.processRow( meta, new CalculatorData() );
} catch ( KettleException ke ) {
ke.printStackTrace();
fail();
}
}
@Test
public void testRound2() throws KettleException {
assertRound2( 1.0, 1.2, 0 );
assertRound2( 2.0, 1.5, 0 );
assertRound2( 2.0, 1.7, 0 );
assertRound2( 2.0, 2.2, 0 );
assertRound2( 2.0, 2.5, 0 );
assertRound2( 3.0, 2.7, 0 );
assertRound2( -1.0, -1.2, 0 );
assertRound2( -2.0, -1.5, 0 );
assertRound2( -2.0, -1.7, 0 );
assertRound2( -2.0, -2.2, 0 );
assertRound2( -2.0, -2.5, 0 );
assertRound2( -3.0, -2.7, 0 );
}
public void assertRound2( final double expectedResult, final double value, final long precision )
throws KettleException {
RowMeta inputRowMeta = new RowMeta();
ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" );
ValueMetaInteger precisionMeta = new ValueMetaInteger( "Precision" );
inputRowMeta.addValueMeta( valueMeta );
inputRowMeta.addValueMeta( precisionMeta );
RowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value, precision } );
inputRowSet.setRowMeta( inputRowMeta );
Calculator calculator = new Calculator( smh.stepMeta, smh.stepDataInterface, 0, smh.transMeta, smh.trans );
calculator.getInputRowSets().add( inputRowSet );
calculator.setInputRowMeta( inputRowMeta );
calculator.init( smh.initStepMetaInterface, smh.initStepDataInterface );
CalculatorMeta meta = new CalculatorMeta();
meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test",
CalculatorMetaFunction.CALC_ROUND_2, "Value", "Precision", null, ValueMetaInterface.TYPE_NUMBER, 2, 0, false,
"", "", "", "" ) } );
// Verify output
try {
calculator.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
assertEquals( expectedResult, row[2] );
}
} );
calculator.processRow( meta, new CalculatorData() );
} catch ( KettleException ke ) {
ke.printStackTrace();
fail();
}
}
@Test
public void testRoundStd() throws KettleException {
assertRoundStd( 1.0, 1.2 );
assertRoundStd( 2.0, 1.5 );
assertRoundStd( 2.0, 1.7 );
assertRoundStd( 2.0, 2.2 );
assertRoundStd( 3.0, 2.5 );
assertRoundStd( 3.0, 2.7 );
assertRoundStd( -1.0, -1.2 );
assertRoundStd( -2.0, -1.5 );
assertRoundStd( -2.0, -1.7 );
assertRoundStd( -2.0, -2.2 );
assertRoundStd( -3.0, -2.5 );
assertRoundStd( -3.0, -2.7 );
}
public void assertRoundStd( final double expectedResult, final double value ) throws KettleException {
RowMeta inputRowMeta = new RowMeta();
ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" );
inputRowMeta.addValueMeta( valueMeta );
RowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value } );
inputRowSet.setRowMeta( inputRowMeta );
Calculator calculator = new Calculator( smh.stepMeta, smh.stepDataInterface, 0, smh.transMeta, smh.trans );
calculator.getInputRowSets().add( inputRowSet );
calculator.setInputRowMeta( inputRowMeta );
calculator.init( smh.initStepMetaInterface, smh.initStepDataInterface );
CalculatorMeta meta = new CalculatorMeta();
meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test",
CalculatorMetaFunction.CALC_ROUND_STD_1, "Value", null, null, ValueMetaInterface.TYPE_NUMBER, 2, 0, false, "",
"", "", "" ) } );
// Verify output
try {
calculator.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
assertEquals( expectedResult, row[1] );
}
} );
calculator.processRow( meta, new CalculatorData() );
} catch ( KettleException ke ) {
ke.printStackTrace();
fail();
}
}
@Test
public void testRoundStd2() throws KettleException {
assertRoundStd2( 1.0, 1.2, 0 );
assertRoundStd2( 2.0, 1.5, 0 );
assertRoundStd2( 2.0, 1.7, 0 );
assertRoundStd2( 2.0, 2.2, 0 );
assertRoundStd2( 3.0, 2.5, 0 );
assertRoundStd2( 3.0, 2.7, 0 );
assertRoundStd2( -1.0, -1.2, 0 );
assertRoundStd2( -2.0, -1.5, 0 );
assertRoundStd2( -2.0, -1.7, 0 );
assertRoundStd2( -2.0, -2.2, 0 );
assertRoundStd2( -3.0, -2.5, 0 );
assertRoundStd2( -3.0, -2.7, 0 );
}
public void assertRoundStd2( final double expectedResult, final double value, final long precision )
throws KettleException {
RowMeta inputRowMeta = new RowMeta();
ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" );
ValueMetaInteger precisionMeta = new ValueMetaInteger( "Precision" );
inputRowMeta.addValueMeta( valueMeta );
inputRowMeta.addValueMeta( precisionMeta );
RowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value, precision } );
inputRowSet.setRowMeta( inputRowMeta );
Calculator calculator = new Calculator( smh.stepMeta, smh.stepDataInterface, 0, smh.transMeta, smh.trans );
calculator.getInputRowSets().add( inputRowSet );
calculator.setInputRowMeta( inputRowMeta );
calculator.init( smh.initStepMetaInterface, smh.initStepDataInterface );
CalculatorMeta meta = new CalculatorMeta();
meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test",
CalculatorMetaFunction.CALC_ROUND_STD_2, "Value", "Precision", null, ValueMetaInterface.TYPE_NUMBER, 2, 0,
false, "", "", "", "" ) } );
// Verify output
try {
calculator.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
assertEquals( expectedResult, row[2] );
}
} );
calculator.processRow( meta, new CalculatorData() );
} catch ( KettleException ke ) {
ke.printStackTrace();
fail();
}
}
}