Refactored some code in OFFSET implementation. Added test cases showing comparisons with BoolEval.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@888555 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-12-08 20:08:59 +00:00
parent 72eaea0704
commit f26db72b4b
3 changed files with 53 additions and 52 deletions

View File

@ -18,13 +18,10 @@
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* Implementation for Excel function OFFSET()<p/>
@ -223,43 +220,8 @@ public final class Offset implements Function {
/**
* OFFSET's numeric arguments (2..5) have similar processing rules
*/
private static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
double d = evaluateDoubleArg(eval, srcCellRow, srcCellCol);
return convertDoubleToInt(d);
}
/**
* Fractional values are silently truncated by Excel.
* Truncation is toward negative infinity.
*/
/* package */ static int convertDoubleToInt(double d) {
// Note - the standard java type conversion from double to int truncates toward zero.
// but Math.floor() truncates toward negative infinity
return (int)Math.floor(d);
}
private static double evaluateDoubleArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcCellRow, srcCellCol);
if (ve instanceof NumericValueEval) {
return ((NumericValueEval) ve).getNumberValue();
}
if (ve instanceof StringEval) {
StringEval se = (StringEval) ve;
Double d = OperandResolver.parseDouble(se.getStringValue());
if(d == null) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
return d.doubleValue();
}
if (ve instanceof BoolEval) {
// in the context of OFFSET, booleans resolve to 0 and 1.
if(((BoolEval) ve).getBooleanValue()) {
return 1;
}
return 0;
}
throw new RuntimeException("Unexpected eval type (" + ve.getClass().getName() + ")");
return OperandResolver.coerceValueToInt(ve);
}
}

View File

@ -95,6 +95,37 @@ public final class TestEqualEval extends TestCase {
return be.getBooleanValue();
}
public void testBooleanCompares() {
confirmCompares(BoolEval.TRUE, new StringEval("TRUE"), +1);
confirmCompares(BoolEval.TRUE, new NumberEval(1.0), +1);
confirmCompares(BoolEval.TRUE, BoolEval.TRUE, 0);
confirmCompares(BoolEval.TRUE, BoolEval.FALSE, +1);
confirmCompares(BoolEval.FALSE, new StringEval("TRUE"), +1);
confirmCompares(BoolEval.FALSE, new StringEval("FALSE"), +1);
confirmCompares(BoolEval.FALSE, new NumberEval(0.0), +1);
confirmCompares(BoolEval.FALSE, BoolEval.FALSE, 0);
}
private static void confirmCompares(ValueEval a, ValueEval b, int expRes) {
confirm(a, b, expRes>0, EI.GreaterThan);
confirm(a, b, expRes>=0, EI.GreaterEqual);
confirm(a, b, expRes==0, EI.Equal);
confirm(a, b, expRes<=0, EI.LessEqual);
confirm(a, b, expRes<0, EI.LessThan);
confirm(b, a, expRes<0, EI.GreaterThan);
confirm(b, a, expRes<=0, EI.GreaterEqual);
confirm(b, a, expRes==0, EI.Equal);
confirm(b, a, expRes>=0, EI.LessEqual);
confirm(b, a, expRes>0, EI.LessThan);
}
private static void confirm(ValueEval a, ValueEval b, boolean expectedResult, Function cmpOp) {
ValueEval[] args = { a, b, };
ValueEval result = evaluate(cmpOp, args, 10, 20);
assertEquals(BoolEval.class, result.getClass());
assertEquals(expectedResult, ((BoolEval) result).getBooleanValue());
}
/**
* Bug 47198 involved a formula "-A1=0" where cell A1 was 0.0.
* Excel evaluates "-A1=0" to TRUE, not because it thinks -0.0==0.0

View File

@ -17,32 +17,41 @@
package org.apache.poi.hssf.record.formula.functions;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.Offset.LinearOffsetRange;
/**
* Tests for OFFSET function implementation
*
*
* @author Josh Micich
*/
public final class TestOffset extends TestCase {
private static void confirmDoubleConvert(double doubleVal, int expected) {
assertEquals(expected, Offset.convertDoubleToInt(doubleVal));
try {
assertEquals(expected, Offset.evaluateIntArg(new NumberEval(doubleVal), -1, -1));
} catch (EvaluationException e) {
throw new AssertionFailedError("Unexpected error '" + e.getErrorEval().toString() + "'.");
}
}
/**
* Excel's double to int conversion (for function 'OFFSET()') behaves more like Math.floor().
* Note - negative values are not symmetrical
* Fractional values are silently truncated.
* Truncation is toward negative infinity.
*/
public void testDoubleConversion() {
confirmDoubleConvert(100.09, 100);
confirmDoubleConvert(100.01, 100);
confirmDoubleConvert(100.00, 100);
confirmDoubleConvert(99.99, 99);
confirmDoubleConvert(+2.01, +2);
confirmDoubleConvert(+2.00, +2);
confirmDoubleConvert(+1.99, +1);
@ -62,25 +71,25 @@ public final class TestOffset extends TestCase {
public void testLinearOffsetRange() {
LinearOffsetRange lor;
lor = new LinearOffsetRange(3, 2);
assertEquals(3, lor.getFirstIndex());
assertEquals(4, lor.getLastIndex());
lor = lor.normaliseAndTranslate(0); // expected no change
assertEquals(3, lor.getFirstIndex());
assertEquals(4, lor.getLastIndex());
lor = lor.normaliseAndTranslate(5);
assertEquals(8, lor.getFirstIndex());
assertEquals(9, lor.getLastIndex());
// negative length
lor = new LinearOffsetRange(6, -4).normaliseAndTranslate(0);
assertEquals(3, lor.getFirstIndex());
assertEquals(6, lor.getLastIndex());
// bounds checking
lor = new LinearOffsetRange(0, 100);
assertFalse(lor.isOutOfBounds(0, 16383));
@ -88,5 +97,4 @@ public final class TestOffset extends TestCase {
assertTrue(lor.isOutOfBounds(0, 16383));
assertFalse(lor.isOutOfBounds(0, 65535));
}
}