/*! ****************************************************************************** * * Hop : The Hop Orchestration Platform * * http://www.project-hop.org * ******************************************************************************* * * 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.apache.hop.pipeline.transforms.calculator; import org.apache.hop.core.Const; import org.apache.hop.core.HopEnvironment; import org.apache.hop.core.IRowSet; import org.apache.hop.core.exception.HopException; import org.apache.hop.core.exception.HopTransformException; import org.apache.hop.core.logging.ILoggingObject; import org.apache.hop.core.row.IRowMeta; import org.apache.hop.core.row.IValueMeta; import org.apache.hop.core.row.RowMeta; import org.apache.hop.core.row.ValueDataUtil; import org.apache.hop.core.row.value.ValueMetaInteger; import org.apache.hop.core.row.value.ValueMetaNumber; import org.apache.hop.junit.rules.RestoreHopEngineEnvironment; import org.apache.hop.pipeline.transform.RowAdapter; import org.apache.hop.pipeline.transforms.mock.TransformMockHelper; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import java.lang.reflect.Field; import java.math.BigDecimal; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; /** * Unit tests for calculator transform * * @author Pavel Sakun * @see Calculator */ public class CalculatorBackwardCompatibilityUnitTest { @ClassRule public static RestoreHopEngineEnvironment env = new RestoreHopEngineEnvironment(); private TransformMockHelper<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 HopException { assertEquals( DEFAULT_ROUND_2_MODE, getRound2Mode() ); setRound2Mode( OBSOLETE_ROUND_2_MODE ); assertEquals( OBSOLETE_ROUND_2_MODE, getRound2Mode() ); HopEnvironment.init(); } @AfterClass public static void restore() throws Exception { setRound2Mode( DEFAULT_ROUND_2_MODE ); assertEquals( DEFAULT_ROUND_2_MODE, getRound2Mode() ); } @Before public void setUp() { smh = new TransformMockHelper<CalculatorMeta, CalculatorData>( "Calculator", CalculatorMeta.class, CalculatorData.class ); when( smh.logChannelFactory.create( any(), any( ILoggingObject.class ) ) ).thenReturn( smh.logChannelInterface ); when( smh.pipeline.isRunning() ).thenReturn( true ); } @After public void cleanUp() { smh.cleanUp(); } @Test public void testRound() throws HopException { 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 HopException { RowMeta inputRowMeta = new RowMeta(); ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" ); inputRowMeta.addValueMeta( valueMeta ); IRowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value } ); inputRowSet.setRowMeta( inputRowMeta ); CalculatorMeta meta = new CalculatorMeta(); meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test", CalculatorMetaFunction.CALC_ROUND_1, "Value", null, null, IValueMeta.TYPE_NUMBER, 2, 0, false, "", "", "", "" ) } ); CalculatorData data = new CalculatorData(); Calculator calculator = new Calculator( smh.transformMeta, meta, data, 0, smh.pipelineMeta, smh.pipeline ); calculator.addRowSetToInputRowSets( inputRowSet ); calculator.setInputRowMeta( inputRowMeta ); calculator.init(); // Verify output try { calculator.addRowListener( new RowAdapter() { @Override public void rowWrittenEvent( IRowMeta rowMeta, Object[] row ) throws HopTransformException { assertEquals( expectedResult, row[ 1 ] ); } } ); calculator.processRow(); } catch ( HopException ke ) { ke.printStackTrace(); fail(); } } @Test public void testRound2() throws HopException { 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 HopException { RowMeta inputRowMeta = new RowMeta(); ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" ); ValueMetaInteger precisionMeta = new ValueMetaInteger( "Precision" ); inputRowMeta.addValueMeta( valueMeta ); inputRowMeta.addValueMeta( precisionMeta ); IRowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value, precision } ); inputRowSet.setRowMeta( inputRowMeta ); CalculatorMeta meta = new CalculatorMeta(); meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test", CalculatorMetaFunction.CALC_ROUND_2, "Value", "Precision", null, IValueMeta.TYPE_NUMBER, 2, 0, false, "", "", "", "" ) } ); CalculatorData data = new CalculatorData(); Calculator calculator = new Calculator( smh.transformMeta, meta, data, 0, smh.pipelineMeta, smh.pipeline ); calculator.addRowSetToInputRowSets( inputRowSet ); calculator.setInputRowMeta( inputRowMeta ); calculator.init(); // Verify output try { calculator.addRowListener( new RowAdapter() { @Override public void rowWrittenEvent( IRowMeta rowMeta, Object[] row ) throws HopTransformException { assertEquals( expectedResult, row[ 2 ] ); } } ); calculator.processRow(); } catch ( HopException ke ) { ke.printStackTrace(); fail(); } } @Test public void testRoundStd() throws HopException { 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 HopException { RowMeta inputRowMeta = new RowMeta(); ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" ); inputRowMeta.addValueMeta( valueMeta ); IRowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value } ); inputRowSet.setRowMeta( inputRowMeta ); CalculatorMeta meta = new CalculatorMeta(); meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test", CalculatorMetaFunction.CALC_ROUND_STD_1, "Value", null, null, IValueMeta.TYPE_NUMBER, 2, 0, false, "", "", "", "" ) } ); CalculatorData data = new CalculatorData(); Calculator calculator = new Calculator( smh.transformMeta, meta, data, 0, smh.pipelineMeta, smh.pipeline ); calculator.addRowSetToInputRowSets( inputRowSet ); calculator.setInputRowMeta( inputRowMeta ); calculator.init(); // Verify output try { calculator.addRowListener( new RowAdapter() { @Override public void rowWrittenEvent( IRowMeta rowMeta, Object[] row ) throws HopTransformException { assertEquals( expectedResult, row[ 1 ] ); } } ); calculator.processRow(); } catch ( HopException ke ) { ke.printStackTrace(); fail(); } } @Test public void testRoundStd2() throws HopException { 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 HopException { RowMeta inputRowMeta = new RowMeta(); ValueMetaNumber valueMeta = new ValueMetaNumber( "Value" ); ValueMetaInteger precisionMeta = new ValueMetaInteger( "Precision" ); inputRowMeta.addValueMeta( valueMeta ); inputRowMeta.addValueMeta( precisionMeta ); IRowSet inputRowSet = smh.getMockInputRowSet( new Object[] { value, precision } ); inputRowSet.setRowMeta( inputRowMeta ); CalculatorMeta meta = new CalculatorMeta(); meta.setCalculation( new CalculatorMetaFunction[] { new CalculatorMetaFunction( "test", CalculatorMetaFunction.CALC_ROUND_STD_2, "Value", "Precision", null, IValueMeta.TYPE_NUMBER, 2, 0, false, "", "", "", "" ) } ); CalculatorData data = new CalculatorData(); Calculator calculator = new Calculator( smh.transformMeta, meta, data, 0, smh.pipelineMeta, smh.pipeline ); calculator.addRowSetToInputRowSets( inputRowSet ); calculator.setInputRowMeta( inputRowMeta ); calculator.init(); // Verify output try { calculator.addRowListener( new RowAdapter() { @Override public void rowWrittenEvent( IRowMeta rowMeta, Object[] row ) throws HopTransformException { assertEquals( expectedResult, row[ 2 ] ); } } ); calculator.processRow(); } catch ( HopException ke ) { ke.printStackTrace(); fail(); } } }