]> source.dussan.org Git - poi.git/commitdiff
moved common formula-related code to org.apache.poi.ss.formula, eliminated dependenci...
authorYegor Kozlov <yegor@apache.org>
Sun, 21 Nov 2010 11:41:38 +0000 (11:41 +0000)
committerYegor Kozlov <yegor@apache.org>
Sun, 21 Nov 2010 11:41:38 +0000 (11:41 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1037426 13f79535-47bb-0310-9956-ffa450edef68

135 files changed:
src/testcases/org/apache/poi/hssf/model/TestSheet.java
src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java
src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/TestSheetNameFormatter.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/atp/TestRandBetween.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculatorFromSpreadsheet.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/EvalInstances.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestEqualEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestMinusZeroResult.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestMissingArgEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestOperandResolver.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/function/AllFormulaFunctionTests.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/function/ExcelFileFormatDocFunctionExtractor.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/function/TestFunctionMetadataRegistry.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/function/TestReadMissingBuiltInFuncs.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestAverage.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestDays360.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestFind.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestIsBlank.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestLeftRight.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestLen.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestNper.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestOffset.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestPoisson.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestRoundFuncs.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestRowCol.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestSubtotal.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumif.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestText.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestTime.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrim.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrunc.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestValue.java [deleted file]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java [deleted file]
src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java
src/testcases/org/apache/poi/ss/formula/TestCellCacheEntry.java
src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java
src/testcases/org/apache/poi/ss/formula/TestFormulaShifter.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
src/testcases/org/apache/poi/ss/formula/atp/TestRandBetween.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculator.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculatorFromSpreadsheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/AllFormulaEvalTests.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/EvalInstances.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestAreaEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestCircularReferences.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestDivideEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestEqualEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestExternalFunction.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestFormulaBugs.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestFormulasFromSpreadsheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestMinusZeroResult.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestMissingArgEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestOperandResolver.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestPercentEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestRangeEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/TestUnaryPlusEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/eval/forked/TestForkedEvaluator.java
src/testcases/org/apache/poi/ss/formula/function/AllFormulaFunctionTests.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/AbstractNumericTestCase.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/AllIndividualFunctionEvaluationTests.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/EvalFactory.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/NumericFunctionInvoker.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestAverage.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestDate.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestDays360.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestFinanceLib.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestFind.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestIndex.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestIndexFunctionFromSpreadsheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestIndirect.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestIsBlank.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestLeftRight.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestLen.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestLookupFunctionsFromSpreadsheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestMatch.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestMid.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestNper.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestOffset.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestPmt.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestPoisson.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestRoundFuncs.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestRowCol.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestStatsLib.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestSubtotal.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestSumproduct.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestText.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestTime.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestTrim.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestTrunc.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestValue.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestXYNumericFunction.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/usermodel/BaseTestHyperlink.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java

index 7471f46699ee0f398fa5df07270f114506a1438f..5f9a31bd4fc05c212bdd35457c7aa7068fbe632a 100644 (file)
@@ -46,7 +46,7 @@ import org.apache.poi.hssf.record.WindowTwoRecord;
 import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
 import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
-import org.apache.poi.hssf.record.formula.FormulaShifter;
+import org.apache.poi.ss.formula.FormulaShifter;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
index 1547f94565110e3481bba0e44dae59517329fed0..cb99f53acd6365a3b03cfbbc21cf761030118bd7 100644 (file)
@@ -24,7 +24,7 @@ import junit.framework.TestCase;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.RefPtg;
-import org.apache.poi.hssf.record.formula.SharedFormula;
+import org.apache.poi.ss.formula.SharedFormula;
 import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.usermodel.CellValue;
 import org.apache.poi.ss.formula.FormulaParser;
index 248f7ca59d785bf3a829e783b584ae915e54cf06..837afa41b8421334bc0045c067f3cc8bf20547da 100644 (file)
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.formula.eval.AllFormulaEvalTests;
-import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
-import org.apache.poi.hssf.record.formula.functions.AllIndividualFunctionEvaluationTests;
+import org.apache.poi.ss.formula.TestFormulaShifter;
+import org.apache.poi.ss.formula.TestSheetNameFormatter;
+import org.apache.poi.ss.formula.eval.AllFormulaEvalTests;
+import org.apache.poi.ss.formula.function.AllFormulaFunctionTests;
+import org.apache.poi.ss.formula.functions.AllIndividualFunctionEvaluationTests;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java b/src/testcases/org/apache/poi/hssf/record/formula/TestFormulaShifter.java
deleted file mode 100644 (file)
index 55f79e6..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link FormulaShifter}.
- *
- * @author Josh Micich
- */
-public final class TestFormulaShifter extends TestCase {
-       // Note - the expected result row coordinates here were determined/verified
-       // in Excel 2007 by manually testing.
-
-       /**
-        * Tests what happens to area refs when a range of rows from inside, or overlapping are
-        * moved
-        */
-       public void testShiftAreasSourceRows() {
-
-               // all these operations are on an area ref spanning rows 10 to 20
-               AreaPtg aptg  = createAreaPtg(10, 20);
-
-               confirmAreaShift(aptg,  9, 21, 20, 30, 40);
-               confirmAreaShift(aptg, 10, 21, 20, 30, 40);
-               confirmAreaShift(aptg,  9, 20, 20, 30, 40);
-
-               confirmAreaShift(aptg, 8, 11,  -3, 7, 20); // simple expansion of top
-               // rows containing area top being shifted down:
-               confirmAreaShift(aptg, 8, 11,  3, 13, 20);
-               confirmAreaShift(aptg, 8, 11,  7, 17, 20);
-               confirmAreaShift(aptg, 8, 11,  8, 18, 20);
-               confirmAreaShift(aptg, 8, 11,  9, 12, 20); // note behaviour changes here
-               confirmAreaShift(aptg, 8, 11, 10, 12, 21);
-               confirmAreaShift(aptg, 8, 11, 12, 12, 23);
-               confirmAreaShift(aptg, 8, 11, 13, 10, 20);  // ignored
-
-               // rows from within being moved:
-               confirmAreaShift(aptg, 12, 16,  3, 10, 20);  // stay within - no change
-               confirmAreaShift(aptg, 11, 19, 20, 10, 20);  // move completely out - no change
-               confirmAreaShift(aptg, 16, 17, -6, 10, 20);  // moved exactly to top - no change
-               confirmAreaShift(aptg, 16, 17, -7, 11, 20);  // truncation at top
-               confirmAreaShift(aptg, 12, 16,  4, 10, 20);  // moved exactly to bottom - no change
-               confirmAreaShift(aptg, 12, 16,  6, 10, 17);  // truncation at bottom
-
-               // rows containing area bottom being shifted up:
-               confirmAreaShift(aptg, 18, 22, -1, 10, 19); // simple contraction at bottom
-               confirmAreaShift(aptg, 18, 22, -7, 10, 13); // simple contraction at bottom
-               confirmAreaShift(aptg, 18, 22, -8, 10, 17); // top calculated differently here
-               confirmAreaShift(aptg, 18, 22, -9,  9, 17);
-               confirmAreaShift(aptg, 18, 22,-15, 10, 20); // no change because range would be turned inside out
-               confirmAreaShift(aptg, 15, 19, -7, 13, 20); // dest truncates top (even though src is from inside range)
-               confirmAreaShift(aptg, 19, 23,-12,  7, 18); // complex: src encloses bottom, dest encloses top
-
-               confirmAreaShift(aptg, 18, 22,  5, 10, 25); // simple expansion at bottom
-       }
-       /**
-        * Tests what happens to an area ref when some outside rows are moved to overlap
-        * that area ref
-        */
-       public void testShiftAreasDestRows() {
-               // all these operations are on an area ref spanning rows 20 to 25
-               AreaPtg aptg  = createAreaPtg(20, 25);
-
-               // no change because no overlap:
-               confirmAreaShift(aptg,  5, 10,  9, 20, 25);
-               confirmAreaShift(aptg,  5, 10, 21, 20, 25);
-
-               confirmAreaShift(aptg, 11, 14, 10, 20, 25);
-
-               confirmAreaShift(aptg,   7, 17, 10, -1, -1); // converted to DeletedAreaRef
-               confirmAreaShift(aptg,   5, 15,  7, 23, 25); // truncation at top
-               confirmAreaShift(aptg,  13, 16, 10, 20, 22); // truncation at bottom
-       }
-
-       private static void confirmAreaShift(AreaPtg aptg,
-                       int firstRowMoved, int lastRowMoved, int numberRowsMoved,
-                       int expectedAreaFirstRow, int expectedAreaLastRow) {
-
-               FormulaShifter fs = FormulaShifter.createForRowShift(0, firstRowMoved, lastRowMoved, numberRowsMoved);
-               boolean expectedChanged = aptg.getFirstRow() != expectedAreaFirstRow || aptg.getLastRow() != expectedAreaLastRow;
-
-               AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
-               Ptg[] ptgs = { copyPtg, };
-               boolean actualChanged = fs.adjustFormula(ptgs, 0);
-               if (expectedAreaFirstRow < 0) {
-                       assertEquals(AreaErrPtg.class, ptgs[0].getClass());
-                       return;
-               }
-               assertEquals(expectedChanged, actualChanged);
-               assertEquals(copyPtg, ptgs[0]);  // expected to change in place (although this is not a strict requirement)
-               assertEquals(expectedAreaFirstRow, copyPtg.getFirstRow());
-               assertEquals(expectedAreaLastRow, copyPtg.getLastRow());
-
-       }
-       private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow) {
-               return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, false, false, false, false);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestSheetNameFormatter.java b/src/testcases/org/apache/poi/hssf/record/formula/TestSheetNameFormatter.java
deleted file mode 100644 (file)
index b7c1664..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link SheetNameFormatter}
- * 
- * @author Josh Micich
- */
-public final class TestSheetNameFormatter extends TestCase {
-
-       private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding) {
-               assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
-       }
-
-       /**
-        * Tests main public method 'format' 
-        */
-       public void testFormat() {
-               
-               confirmFormat("abc", "abc");
-               confirmFormat("123", "'123'");
-               
-               confirmFormat("my sheet", "'my sheet'"); // space
-               confirmFormat("A:MEM", "'A:MEM'"); // colon
-
-               confirmFormat("O'Brian", "'O''Brian'"); // single quote gets doubled
-               
-               
-               confirmFormat("3rdTimeLucky", "'3rdTimeLucky'"); // digit in first pos
-               confirmFormat("_", "_"); // plain underscore OK
-               confirmFormat("my_3rd_sheet", "my_3rd_sheet"); // underscores and digits OK
-               confirmFormat("A12220", "'A12220'"); 
-               confirmFormat("TAXRETURN19980415", "TAXRETURN19980415"); 
-       }
-       
-       public void testBooleanLiterals() {
-               confirmFormat("TRUE", "'TRUE'");
-               confirmFormat("FALSE", "'FALSE'");
-               confirmFormat("True", "'True'");
-               confirmFormat("fAlse", "'fAlse'");
-               
-               confirmFormat("Yes", "Yes");
-               confirmFormat("No", "No");
-       }
-       
-       private static void confirmCellNameMatch(String rawSheetName, boolean expected) {
-               assertEquals(expected, SheetNameFormatter.nameLooksLikePlainCellReference(rawSheetName));
-       }
-       
-       /**
-        * Tests functionality to determine whether a sheet name containing only letters and digits
-        * would look (to Excel) like a cell name.
-        */
-       public void testLooksLikePlainCellReference() {
-               
-               confirmCellNameMatch("A1", true);
-               confirmCellNameMatch("a111", true);
-               confirmCellNameMatch("AA", false);
-               confirmCellNameMatch("aa1", true);
-               confirmCellNameMatch("A1A", false);
-               confirmCellNameMatch("A1A1", false);
-               confirmCellNameMatch("Sh3", false);
-               confirmCellNameMatch("SALES20080101", false); // out of range
-       }
-       
-       private static void confirmCellRange(String text, int numberOfPrefixLetters, boolean expected) {
-               String prefix = text.substring(0, numberOfPrefixLetters);
-               String suffix = text.substring(numberOfPrefixLetters);
-               assertEquals(expected, SheetNameFormatter.cellReferenceIsWithinRange(prefix, suffix));
-       }
-       
-       /**
-        * Tests exact boundaries for names that look very close to cell names (i.e. contain 1 or more
-        * letters followed by one or more digits).
-        */
-       public void testCellRange() {
-               confirmCellRange("A1", 1, true);
-               confirmCellRange("a111", 1, true);
-               confirmCellRange("A65536", 1, true);
-               confirmCellRange("A65537", 1, false);
-               confirmCellRange("iv1", 2, true);
-               confirmCellRange("IW1", 2, false);
-               confirmCellRange("AAA1", 3, false);
-               confirmCellRange("a111", 1, true);
-               confirmCellRange("Sheet1", 6, false);
-               confirmCellRange("iV65536", 2, true);  // max cell in Excel 97-2003
-               confirmCellRange("IW65537", 2, false);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/atp/TestRandBetween.java b/src/testcases/org/apache/poi/hssf/record/formula/atp/TestRandBetween.java
deleted file mode 100644 (file)
index 6be56ba..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.atp;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-
-/**
- * Testcase for 'Analysis Toolpak' function RANDBETWEEN()
- * 
- * @author Brendan Nolan
- */
-public class TestRandBetween extends TestCase {
-
-       private Workbook wb;
-       private FormulaEvaluator evaluator;
-       private Cell bottomValueCell;
-       private Cell topValueCell;
-       private Cell formulaCell;
-       
-       @Override
-       protected void setUp() throws Exception {
-               super.setUp();
-               wb = HSSFTestDataSamples.openSampleWorkbook("TestRandBetween.xls");
-               evaluator = wb.getCreationHelper().createFormulaEvaluator();
-               
-               Sheet sheet = wb.createSheet("RandBetweenSheet");
-               Row row = sheet.createRow(0);
-               bottomValueCell = row.createCell(0);
-               topValueCell = row.createCell(1);
-               formulaCell = row.createCell(2, Cell.CELL_TYPE_FORMULA);
-       }
-       
-       @Override
-       protected void tearDown() throws Exception {
-               // TODO Auto-generated method stub
-               super.tearDown();
-       }
-       
-       /**
-        * Check where values are the same
-        */
-       public void testRandBetweenSameValues() {
-               
-               evaluator.clearAllCachedResultValues();
-               formulaCell.setCellFormula("RANDBETWEEN(1,1)");
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(1, formulaCell.getNumericCellValue(), 0);
-               evaluator.clearAllCachedResultValues();
-               formulaCell.setCellFormula("RANDBETWEEN(-1,-1)");
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
-
-       }
-       
-       /**
-        * Check special case where rounded up bottom value is greater than 
-        * top value.
-        */
-       public void testRandBetweenSpecialCase() {
-               
-
-               bottomValueCell.setCellValue(0.05);             
-               topValueCell.setCellValue(0.1);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(1, formulaCell.getNumericCellValue(), 0);
-               bottomValueCell.setCellValue(-0.1);             
-               topValueCell.setCellValue(-0.05);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(0, formulaCell.getNumericCellValue(), 0);
-               bottomValueCell.setCellValue(-1.1);             
-               topValueCell.setCellValue(-1.05);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
-               bottomValueCell.setCellValue(-1.1);             
-               topValueCell.setCellValue(-1.1);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
-       }
-       
-       /**
-        * Check top value of BLANK which Excel will evaluate as 0
-        */
-       public void testRandBetweenTopBlank() {
-
-               bottomValueCell.setCellValue(-1);               
-               topValueCell.setCellType(Cell.CELL_TYPE_BLANK);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertTrue(formulaCell.getNumericCellValue() == 0 || formulaCell.getNumericCellValue() == -1);
-       
-       }
-       /**
-        * Check where input values are of wrong type
-        */
-       public void testRandBetweenWrongInputTypes() {
-               // Check case where bottom input is of the wrong type
-               bottomValueCell.setCellValue("STRING");         
-               topValueCell.setCellValue(1);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
-               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
-               
-               
-               // Check case where top input is of the wrong type
-               bottomValueCell.setCellValue(1);
-               topValueCell.setCellValue("STRING");            
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
-               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
-
-               // Check case where both inputs are of wrong type
-               bottomValueCell.setCellValue("STRING");
-               topValueCell.setCellValue("STRING");            
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
-               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
-       
-       }
-       
-       /**
-        * Check case where bottom is greater than top
-        */
-       public void testRandBetweenBottomGreaterThanTop() {
-
-               // Check case where bottom is greater than top
-               bottomValueCell.setCellValue(1);                
-               topValueCell.setCellValue(0);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
-               assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), formulaCell.getErrorCellValue());              
-               bottomValueCell.setCellValue(1);                
-               topValueCell.setCellType(Cell.CELL_TYPE_BLANK);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
-               assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), formulaCell.getErrorCellValue());
-       }
-       
-       /**
-        * Boundary check of Double MIN and MAX values
-        */
-       public void testRandBetweenBoundaryCheck() {
-
-               bottomValueCell.setCellValue(Double.MIN_VALUE);         
-               topValueCell.setCellValue(Double.MAX_VALUE);
-               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
-               evaluator.clearAllCachedResultValues();
-               evaluator.evaluateFormulaCell(formulaCell);
-               assertTrue(formulaCell.getNumericCellValue() >= Double.MIN_VALUE && formulaCell.getNumericCellValue() <= Double.MAX_VALUE);             
-               
-       }
-       
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java b/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculator.java
deleted file mode 100644 (file)
index bd580f0..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.atp;
-
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.EvaluationException;
-import org.apache.poi.ss.usermodel.DateUtil;
-
-/**
- * Specific test cases for YearFracCalculator
- */
-public final class TestYearFracCalculator extends TestCase {
-
-       public void testBasis1() {
-               confirm(md(1999, 1, 1), md(1999, 4, 5), 1, 0.257534247);
-               confirm(md(1999, 4, 1), md(1999, 4, 5), 1, 0.010958904);
-               confirm(md(1999, 4, 1), md(1999, 4, 4), 1, 0.008219178);
-               confirm(md(1999, 4, 2), md(1999, 4, 5), 1, 0.008219178);
-               confirm(md(1999, 3, 31), md(1999, 4, 3), 1, 0.008219178);
-               confirm(md(1999, 4, 5), md(1999, 4, 8), 1, 0.008219178);
-               confirm(md(1999, 4, 4), md(1999, 4, 7), 1, 0.008219178);
-               confirm(md(2000, 2, 5), md(2000, 6, 1), 0, 0.322222222);
-       }
-
-       private void confirm(double startDate, double endDate, int basis, double expectedValue) {
-               double actualValue;
-               try {
-                       actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
-               } catch (EvaluationException e) {
-                       throw new RuntimeException(e);
-               }
-               double diff = actualValue - expectedValue;
-               if (Math.abs(diff) >  0.000000001) {
-                       double hours = diff * 365 * 24;
-                       System.out.println(startDate + " " + endDate + " off by " + hours + " hours");
-                       assertEquals(expectedValue, actualValue, 0.000000001);
-               }
-               
-       }
-
-       private static double md(int year, int month, int day) {
-               Calendar c = new GregorianCalendar();
-               
-               c.set(year, month-1, day, 0, 0, 0);
-               c.set(Calendar.MILLISECOND, 0);
-               return DateUtil.getExcelDate(c.getTime());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculatorFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculatorFromSpreadsheet.java
deleted file mode 100644 (file)
index 37d1bb3..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.atp;
-
-import java.io.PrintStream;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Iterator;
-
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.ComparisonFailure;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.eval.EvaluationException;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFDateUtil;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Tests YearFracCalculator using test-cases listed in a sample spreadsheet
- * 
- * @author Josh Micich
- */
-public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
-       
-       private static final class SS {
-
-               public static final int BASIS_COLUMN = 1; // "B"
-               public static final int START_YEAR_COLUMN = 2; // "C"
-               public static final int END_YEAR_COLUMN = 5; // "F"
-               public static final int YEARFRAC_FORMULA_COLUMN = 11; // "L"
-               public static final int EXPECTED_RESULT_COLUMN = 13; // "N"
-       }
-
-       public void testAll() {
-               
-               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls");
-               HSSFSheet sheet = wb.getSheetAt(0);
-               HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb);
-               int nSuccess = 0;
-               int nFailures = 0;
-               int nUnexpectedErrors = 0;
-               Iterator rowIterator = sheet.rowIterator();
-               while(rowIterator.hasNext()) {
-                       HSSFRow row = (HSSFRow) rowIterator.next();
-                       
-                       HSSFCell cell = row.getCell(SS.YEARFRAC_FORMULA_COLUMN);
-                       if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
-                               continue;
-                       }
-                       try {
-                               processRow(row, cell, formulaEvaluator);
-                               nSuccess++;
-                       } catch (RuntimeException e) {
-                               nUnexpectedErrors ++;
-                               printShortStackTrace(System.err, e);
-                       } catch (AssertionFailedError e) {
-                               nFailures ++;
-                               printShortStackTrace(System.err, e);
-                       }
-               }
-               if (nUnexpectedErrors + nFailures > 0) {
-                       String msg = nFailures + " failures(s) and " + nUnexpectedErrors 
-                               + " unexpected errors(s) occurred. See stderr for details";
-                       throw new AssertionFailedError(msg);
-               }
-               if (nSuccess < 1) {
-                       throw new RuntimeException("No test sample cases found");
-               }
-       }
-       
-       private static void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator) {
-               
-               double startDate = makeDate(row, SS.START_YEAR_COLUMN);
-               double endDate = makeDate(row, SS.END_YEAR_COLUMN);
-               
-               int basis = getIntCell(row, SS.BASIS_COLUMN);
-               
-               double expectedValue = getDoubleCell(row, SS.EXPECTED_RESULT_COLUMN);
-               
-               double actualValue;
-               try {
-                       actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
-               } catch (EvaluationException e) {
-                       throw new RuntimeException(e);
-               }
-               if (expectedValue != actualValue) {
-                       throw new ComparisonFailure("Direct calculate failed - row " + (row.getRowNum()+1), 
-                                       String.valueOf(expectedValue), String.valueOf(actualValue));
-               }
-               actualValue = formulaEvaluator.evaluate(cell).getNumberValue();
-               if (expectedValue != actualValue) {
-                       throw new ComparisonFailure("Formula evaluate failed - row " + (row.getRowNum()+1), 
-                                       String.valueOf(expectedValue), String.valueOf(actualValue));
-               }
-       }
-
-       private static double makeDate(HSSFRow row, int yearColumn) {
-               int year = getIntCell(row, yearColumn + 0);
-               int month = getIntCell(row, yearColumn + 1);
-               int day = getIntCell(row, yearColumn + 2);
-               Calendar c = new GregorianCalendar(year, month-1, day, 0, 0, 0);
-               c.set(Calendar.MILLISECOND, 0);
-               return HSSFDateUtil.getExcelDate(c.getTime());
-       }
-
-       private static int getIntCell(HSSFRow row, int colIx) {
-               double dVal = getDoubleCell(row, colIx);
-               if (Math.floor(dVal) != dVal) {
-                       throw new RuntimeException("Non integer value (" + dVal 
-                                       + ") cell found at column " + (char)('A' + colIx));
-               }
-               return (int)dVal;
-       }
-
-       private static double getDoubleCell(HSSFRow row, int colIx) {
-               HSSFCell cell = row.getCell(colIx);
-               if (cell == null) {
-                       throw new RuntimeException("No cell found at column " + colIx);
-               }
-               double dVal = cell.getNumericCellValue();
-               return dVal;
-       }
-
-       /**
-        * Useful to keep output concise when expecting many failures to be reported by this test case
-        * TODO - refactor duplicates in other Test~FromSpreadsheet classes
-        */
-       private static void printShortStackTrace(PrintStream ps, Throwable e) {
-               StackTraceElement[] stes = e.getStackTrace();
-               
-               int startIx = 0;
-               // skip any top frames inside junit.framework.Assert
-               while(startIx<stes.length) {
-                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
-                               break;
-                       }
-                       startIx++;
-               }
-               // skip bottom frames (part of junit framework)
-               int endIx = startIx+1;
-               while(endIx < stes.length) {
-                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
-                               break;
-                       }
-                       endIx++;
-               }
-               if(startIx >= endIx) {
-                       // something went wrong. just print the whole stack trace
-                       e.printStackTrace(ps);
-               }
-               endIx -= 4; // skip 4 frames of reflection invocation
-               ps.println(e.toString());
-               for(int i=startIx; i<endIx; i++) {
-                       ps.println("\tat " + stes[i].toString());
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java
deleted file mode 100644 (file)
index 325e2e9..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-/**
- * Collects all tests the package <tt>org.apache.poi.hssf.record.formula.eval</tt>.
- *
- * @author Josh Micich
- */
-public class AllFormulaEvalTests {
-
-       public static Test suite() {
-               TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
-               result.addTestSuite(TestAreaEval.class);
-               result.addTestSuite(TestCircularReferences.class);
-               result.addTestSuite(TestDivideEval.class);
-               result.addTestSuite(TestEqualEval.class);
-               result.addTestSuite(TestExternalFunction.class);
-               result.addTestSuite(TestFormulaBugs.class);
-               result.addTestSuite(TestFormulasFromSpreadsheet.class);
-               result.addTestSuite(TestMinusZeroResult.class);
-               result.addTestSuite(TestMissingArgEval.class);
-               result.addTestSuite(TestPercentEval.class);
-               result.addTestSuite(TestRangeEval.class);
-               result.addTestSuite(TestUnaryPlusEval.class);
-               return result;
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/EvalInstances.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/EvalInstances.java
deleted file mode 100644 (file)
index b607693..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import org.apache.poi.hssf.record.formula.functions.Function;
-
-/**
- * Collects eval instances for easy access by tests in this package
- *
- * @author Josh Micich
- */
-final class EvalInstances {
-       private EvalInstances() {
-               // no instances of this class
-       }
-
-       public static final Function Add = TwoOperandNumericOperation.AddEval;
-       public static final Function Subtract = TwoOperandNumericOperation.SubtractEval;
-       public static final Function Multiply = TwoOperandNumericOperation.MultiplyEval;
-       public static final Function Divide = TwoOperandNumericOperation.DivideEval;
-
-       public static final Function Power = TwoOperandNumericOperation.PowerEval;
-
-       public static final Function Percent = PercentEval.instance;
-
-       public static final Function UnaryMinus = UnaryMinusEval.instance;
-       public static final Function UnaryPlus = UnaryPlusEval.instance;
-
-       public static final Function Equal = RelationalOperationEval.EqualEval;
-       public static final Function LessThan = RelationalOperationEval.LessThanEval;
-       public static final Function LessEqual = RelationalOperationEval.LessEqualEval;
-       public static final Function GreaterThan = RelationalOperationEval.GreaterThanEval;
-       public static final Function GreaterEqual = RelationalOperationEval.GreaterEqualEval;
-       public static final Function NotEqual = RelationalOperationEval.NotEqualEval;
-
-       public static final Function Range = RangeEval.instance;
-       public static final Function Concat = ConcatEval.instance;
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java
deleted file mode 100644 (file)
index 65e4e7d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.AreaPtg;
-import org.apache.poi.hssf.record.formula.functions.EvalFactory;
-
-/**
- * Tests for <tt>AreaEval</tt>
- *
- * @author Josh Micich
- */
-public final class TestAreaEval extends TestCase {
-
-       public void testGetValue_bug44950() {
-               // TODO - this test probably isn't testing much anymore
-               AreaPtg ptg = new AreaPtg("B2:D3");
-               NumberEval one = new NumberEval(1);
-               ValueEval[] values = {
-                               one,
-                               new NumberEval(2),
-                               new NumberEval(3),
-                               new NumberEval(4),
-                               new NumberEval(5),
-                               new NumberEval(6),
-               };
-               AreaEval ae = EvalFactory.createAreaEval(ptg, values);
-               if (one == ae.getAbsoluteValue(1, 2)) {
-                       throw new AssertionFailedError("Identified bug 44950 a");
-               }
-               confirm(1, ae, 1, 1);
-               confirm(2, ae, 1, 2);
-               confirm(3, ae, 1, 3);
-               confirm(4, ae, 2, 1);
-               confirm(5, ae, 2, 2);
-               confirm(6, ae, 2, 3);
-
-       }
-
-       private static void confirm(int expectedValue, AreaEval ae, int row, int col) {
-               NumberEval v = (NumberEval) ae.getAbsoluteValue(row, col);
-               assertEquals(expectedValue, v.getNumberValue(), 0.0);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java
deleted file mode 100644 (file)
index 878b7bd..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-/**
- * Tests HSSFFormulaEvaluator for its handling of cell formula circular references.
- *
- * @author Josh Micich
- */
-public final class TestCircularReferences extends TestCase {
-       /**
-        * Translates StackOverflowError into AssertionFailedError
-        */
-       private static CellValue evaluateWithCycles(HSSFWorkbook wb, HSSFCell testCell)
-                       throws AssertionFailedError {
-               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
-               try {
-                       return evaluator.evaluate(testCell);
-               } catch (StackOverflowError e) {
-                       throw new AssertionFailedError( "circular reference caused stack overflow error");
-               }
-       }
-       /**
-        * Makes sure that the specified evaluated cell value represents a circular reference error.
-        */
-       private static void confirmCycleErrorCode(CellValue cellValue) {
-               assertTrue(cellValue.getCellType() == HSSFCell.CELL_TYPE_ERROR);
-               assertEquals(ErrorEval.CIRCULAR_REF_ERROR.getErrorCode(), cellValue.getErrorValue());
-       }
-
-
-       /**
-        * ASF Bugzilla Bug 44413
-        * "INDEX() formula cannot contain its own location in the data array range"
-        */
-       public void testIndexFormula() {
-
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-
-               int colB = 1;
-               sheet.createRow(0).createCell(colB).setCellValue(1);
-               sheet.createRow(1).createCell(colB).setCellValue(2);
-               sheet.createRow(2).createCell(colB).setCellValue(3);
-               HSSFRow row4 = sheet.createRow(3);
-               HSSFCell testCell = row4.createCell(0);
-               // This formula should evaluate to the contents of B2,
-               testCell.setCellFormula("INDEX(A1:B4,2,2)");
-               // However the range A1:B4 also includes the current cell A4.  If the other parameters
-               // were 4 and 1, this would represent a circular reference.  Prior to v3.2 POI would
-               // 'fully' evaluate ref arguments before invoking operators, which raised the possibility of
-               // cycles / StackOverflowErrors.
-
-
-               CellValue cellValue = evaluateWithCycles(wb, testCell);
-
-               assertTrue(cellValue.getCellType() == HSSFCell.CELL_TYPE_NUMERIC);
-               assertEquals(2, cellValue.getNumberValue(), 0);
-       }
-
-       /**
-        * Cell A1 has formula "=A1"
-        */
-       public void testSimpleCircularReference() {
-
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-
-               HSSFRow row = sheet.createRow(0);
-               HSSFCell testCell = row.createCell(0);
-               testCell.setCellFormula("A1");
-
-               CellValue cellValue = evaluateWithCycles(wb, testCell);
-
-               confirmCycleErrorCode(cellValue);
-       }
-
-       /**
-        * A1=B1, B1=C1, C1=D1, D1=A1
-        */
-       public void testMultiLevelCircularReference() {
-
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-
-               HSSFRow row = sheet.createRow(0);
-               row.createCell(0).setCellFormula("B1");
-               row.createCell(1).setCellFormula("C1");
-               row.createCell(2).setCellFormula("D1");
-               HSSFCell testCell = row.createCell(3);
-               testCell.setCellFormula("A1");
-
-               CellValue cellValue = evaluateWithCycles(wb, testCell);
-
-               confirmCycleErrorCode(cellValue);
-       }
-
-       public void testIntermediateCircularReferenceResults_bug46898() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-
-               HSSFRow row = sheet.createRow(0);
-
-               HSSFCell cellA1 = row.createCell(0);
-               HSSFCell cellB1 = row.createCell(1);
-               HSSFCell cellC1 = row.createCell(2);
-               HSSFCell cellD1 = row.createCell(3);
-               HSSFCell cellE1 = row.createCell(4);
-
-               cellA1.setCellFormula("IF(FALSE, 1+B1, 42)");
-               cellB1.setCellFormula("1+C1");
-               cellC1.setCellFormula("1+D1");
-               cellD1.setCellFormula("1+E1");
-               cellE1.setCellFormula("1+A1");
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv;
-
-               // Happy day flow - evaluate A1 first
-               cv = fe.evaluate(cellA1);
-               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(42.0, cv.getNumberValue(), 0.0);
-               cv = fe.evaluate(cellB1); // no circ-ref-error because A1 result is cached
-               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(46.0, cv.getNumberValue(), 0.0);
-
-               // Show the bug - evaluate another cell from the loop first
-               fe.clearAllCachedResultValues();
-               cv = fe.evaluate(cellB1);
-               if (cv.getCellType() == ErrorEval.CIRCULAR_REF_ERROR.getErrorCode()) {
-                       throw new AssertionFailedError("Identified bug 46898");
-               }
-               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(46.0, cv.getNumberValue(), 0.0);
-
-               // start evaluation on another cell
-               fe.clearAllCachedResultValues();
-               cv = fe.evaluate(cellE1);
-               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(43.0, cv.getNumberValue(), 0.0);
-
-
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java
deleted file mode 100644 (file)
index eedcbf9..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.functions.EvalFactory;
-import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
-
-/**
- * Test for divide operator evaluator.
- *
- * @author Josh Micich
- */
-public final class TestDivideEval extends TestCase {
-
-       private static void confirm(ValueEval arg0, ValueEval arg1, double expectedResult) {
-               ValueEval[] args = {
-                       arg0, arg1,
-               };
-
-               double result = NumericFunctionInvoker.invoke(EvalInstances.Divide, args, 0, 0);
-
-               assertEquals(expectedResult, result, 0);
-       }
-
-       public void testBasic() {
-               confirm(new NumberEval(5), new NumberEval(2), 2.5);
-               confirm(new NumberEval(3), new NumberEval(16), 0.1875);
-               confirm(new NumberEval(-150), new NumberEval(-15), 10.0);
-               confirm(new StringEval("0.2"), new NumberEval(0.05), 4.0);
-               confirm(BoolEval.TRUE, new StringEval("-0.2"), -5.0);
-       }
-
-       public void test1x1Area() {
-               AreaEval ae0 = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
-               AreaEval ae1 = EvalFactory.createAreaEval("C2:C2", new ValueEval[] { new NumberEval(10), });
-               confirm(ae0, ae1, 5);
-       }
-       public void testDivZero() {
-               ValueEval[] args = {
-                       new NumberEval(5), NumberEval.ZERO,
-               };
-               ValueEval result = EvalInstances.Divide.evaluate(args, 0, (short) 0);
-               assertEquals(ErrorEval.DIV_ZERO, result);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestEqualEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestEqualEval.java
deleted file mode 100644 (file)
index 739b32c..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.functions.EvalFactory;
-import org.apache.poi.hssf.record.formula.functions.Function;
-
-/**
- * Test for {@link EqualEval}
- *
- * @author Josh Micich
- */
-public final class TestEqualEval extends TestCase {
-       // convenient access to namepace
-       private static final EvalInstances EI = null;
-
-       /**
-        * Test for bug observable at svn revision 692218 (Sep 2008)<br/>
-        * The value from a 1x1 area should be taken immediately, regardless of srcRow and srcCol
-        */
-       public void test1x1AreaOperand() {
-
-               ValueEval[] values = { BoolEval.FALSE, };
-               ValueEval[] args = {
-                       EvalFactory.createAreaEval("B1:B1", values),
-                       BoolEval.FALSE,
-               };
-               ValueEval result = evaluate(EI.Equal, args, 10, 10);
-               if (result instanceof ErrorEval) {
-                       if (result == ErrorEval.VALUE_INVALID) {
-                               throw new AssertionFailedError("Identified bug in evaluation of 1x1 area");
-                       }
-               }
-               assertEquals(BoolEval.class, result.getClass());
-               assertTrue(((BoolEval)result).getBooleanValue());
-       }
-       /**
-        * Empty string is equal to blank
-        */
-       public void testBlankEqualToEmptyString() {
-
-               ValueEval[] args = {
-                       new StringEval(""),
-                       BlankEval.instance,
-               };
-               ValueEval result = evaluate(EI.Equal, args, 10, 10);
-               assertEquals(BoolEval.class, result.getClass());
-               BoolEval be = (BoolEval) result;
-               if (!be.getBooleanValue()) {
-                       throw new AssertionFailedError("Identified bug blank/empty string equality");
-               }
-               assertTrue(be.getBooleanValue());
-       }
-
-       /**
-        * Test for bug 46613 (observable at svn r737248)
-        */
-       public void testStringInsensitive_bug46613() {
-               if (!evalStringCmp("abc", "aBc", EI.Equal)) {
-                       throw new AssertionFailedError("Identified bug 46613");
-               }
-               assertTrue(evalStringCmp("abc", "aBc", EI.Equal));
-               assertTrue(evalStringCmp("ABC", "azz", EI.LessThan));
-               assertTrue(evalStringCmp("abc", "AZZ", EI.LessThan));
-               assertTrue(evalStringCmp("ABC", "aaa", EI.GreaterThan));
-               assertTrue(evalStringCmp("abc", "AAA", EI.GreaterThan));
-       }
-
-       private static boolean evalStringCmp(String a, String b, Function cmpOp) {
-               ValueEval[] args = {
-                       new StringEval(a),
-                       new StringEval(b),
-               };
-               ValueEval result = evaluate(cmpOp, args, 10, 20);
-               assertEquals(BoolEval.class, result.getClass());
-               BoolEval be = (BoolEval) result;
-               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
-        * but because "-A1" evaluated to +0.0
-        * <p/>
-        * Note - the original diagnosis of bug 47198 was that
-        * "Excel considers -0.0 to be equal to 0.0" which is NQR
-        * See {@link TestMinusZeroResult} for more specific tests regarding -0.0.
-        */
-       public void testZeroEquality_bug47198() {
-               NumberEval zero = new NumberEval(0.0);
-               NumberEval mZero = (NumberEval) evaluate(UnaryMinusEval.instance, new ValueEval[] { zero, }, 0, 0);
-               if (Double.doubleToLongBits(mZero.getNumberValue()) == 0x8000000000000000L) {
-                       throw new AssertionFailedError("Identified bug 47198: unary minus should convert -0.0 to 0.0");
-               }
-               ValueEval[] args = { zero, mZero, };
-               BoolEval result = (BoolEval) evaluate(EI.Equal, args, 0, 0);
-               if (!result.getBooleanValue()) {
-                       throw new AssertionFailedError("Identified bug 47198: -0.0 != 0.0");
-               }
-       }
-
-       public void testRounding_bug47598() {
-               double x = 1+1.0028-0.9973; // should be 1.0055, but has IEEE rounding
-               assertFalse(x == 1.0055);
-
-               NumberEval a = new NumberEval(x);
-               NumberEval b = new NumberEval(1.0055);
-               assertEquals("1.0055", b.getStringValue());
-
-               ValueEval[] args = { a, b, };
-               BoolEval result = (BoolEval) evaluate(EI.Equal, args, 0, 0);
-               if (!result.getBooleanValue()) {
-                       throw new AssertionFailedError("Identified bug 47598: 1+1.0028-0.9973 != 1.0055");
-               }
-       }
-
-       private static ValueEval evaluate(Function oper, ValueEval[] args, int srcRowIx, int srcColIx) {
-               return oper.evaluate(args, srcRowIx, (short) srcColIx);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
deleted file mode 100644 (file)
index 2cfbbfe..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
-import org.apache.poi.hssf.record.formula.udf.DefaultUDFFinder;
-import org.apache.poi.hssf.record.formula.udf.AggregatingUDFFinder;
-import org.apache.poi.hssf.record.formula.udf.UDFFinder;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.OperationEvaluationContext;
-
-/**
- * @author Josh Micich
- * @author Petr Udalau - registering UDFs in workbook and using ToolPacks.
- */
-public final class TestExternalFunction extends TestCase {
-
-       private static class MyFunc implements FreeRefFunction {
-               public MyFunc() {
-                       //
-               }
-
-               public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
-                       if (args.length != 1 || !(args[0] instanceof StringEval)) {
-                               return ErrorEval.VALUE_INVALID;
-                       }
-                       StringEval input = (StringEval) args[0];
-                       return new StringEval(input.getStringValue() + "abc");
-               }
-       }
-
-       private static class MyFunc2 implements FreeRefFunction {
-               public MyFunc2() {
-                       //
-               }
-
-               public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
-                       if (args.length != 1 || !(args[0] instanceof StringEval)) {
-                               return ErrorEval.VALUE_INVALID;
-                       }
-                       StringEval input = (StringEval) args[0];
-                       return new StringEval(input.getStringValue() + "abc2");
-               }
-       }
-
-       /**
-        * Checks that an external function can get invoked from the formula
-        * evaluator.
-        */
-       public void testInvoke() {
-               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
-               HSSFSheet sheet = wb.getSheetAt(0);
-
-               /**
-                * register the two test UDFs in a UDF finder, to be passed to the evaluator
-                */
-               UDFFinder udff1 = new DefaultUDFFinder(new String[] { "myFunc", },
-                               new FreeRefFunction[] { new MyFunc(), });
-               UDFFinder udff2 = new DefaultUDFFinder(new String[] { "myFunc2", },
-                               new FreeRefFunction[] { new MyFunc2(), });
-               UDFFinder udff = new AggregatingUDFFinder(udff1, udff2);
-
-
-               HSSFRow row = sheet.getRow(0);
-               HSSFCell myFuncCell = row.getCell(1); // =myFunc("_")
-
-               HSSFCell myFunc2Cell = row.getCell(2); // =myFunc2("_")
-
-               HSSFFormulaEvaluator fe = HSSFFormulaEvaluator.create(wb, null, udff);
-               assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
-               assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java
deleted file mode 100644 (file)
index 1b97905..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Miscellaneous tests for bugzilla entries.<p/> The test name contains the
- * bugzilla bug id.
- * 
- * 
- * @author Josh Micich
- */
-public final class TestFormulaBugs extends TestCase {
-
-       /**
-        * Bug 27349 - VLOOKUP with reference to another sheet.<p/> This test was
-        * added <em>long</em> after the relevant functionality was fixed.
-        */
-       public void test27349() {
-               // 27349-vlookupAcrossSheets.xls is bugzilla/attachment.cgi?id=10622
-               InputStream is = HSSFTestDataSamples.openSampleFileStream("27349-vlookupAcrossSheets.xls");
-               HSSFWorkbook wb;
-               try {
-                       // original bug may have thrown exception here, or output warning to
-                       // stderr
-                       wb = new HSSFWorkbook(is);
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               }
-
-               HSSFSheet sheet = wb.getSheetAt(0);
-               HSSFRow row = sheet.getRow(1);
-               HSSFCell cell = row.getCell(0);
-
-               // this definitely would have failed due to 27349
-               assertEquals("VLOOKUP(1,'DATA TABLE'!$A$8:'DATA TABLE'!$B$10,2)", cell
-                               .getCellFormula());
-
-               // We might as well evaluate the formula
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv = fe.evaluate(cell);
-
-               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(3.0, cv.getNumberValue(), 0.0);
-       }
-
-       /**
-        * Bug 27405 - isnumber() formula always evaluates to false in if statement<p/>
-        * 
-        * seems to be a duplicate of 24925
-        */
-       public void test27405() {
-
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("input");
-               // input row 0
-               HSSFRow row = sheet.createRow(0);
-               HSSFCell cell = row.createCell(0);
-               cell = row.createCell(1);
-               cell.setCellValue(1); // B1
-               // input row 1
-               row = sheet.createRow(1);
-               cell = row.createCell(1);
-               cell.setCellValue(999); // B2
-
-               int rno = 4;
-               row = sheet.createRow(rno);
-               cell = row.createCell(1); // B5
-               cell.setCellFormula("isnumber(b1)");
-               cell = row.createCell(3); // D5
-               cell.setCellFormula("IF(ISNUMBER(b1),b1,b2)");
-
-               if (false) { // set true to check excel file manually
-                       // bug report mentions 'Editing the formula in excel "fixes" the problem.'
-                       try {
-                               FileOutputStream fileOut = new FileOutputStream("27405output.xls");
-                               wb.write(fileOut);
-                               fileOut.close();
-                       } catch (IOException e) {
-                               throw new RuntimeException(e);
-                       }
-               }
-               
-               // use POI's evaluator as an extra sanity check
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv;
-               cv = fe.evaluate(cell);
-               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(1.0, cv.getNumberValue(), 0.0);
-               
-               cv = fe.evaluate(row.getCell(1));
-               assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, cv.getCellType());
-               assertEquals(true, cv.getBooleanValue());
-       }
-
-       /**
-        * Bug 42448 - Can't parse SUMPRODUCT(A!C7:A!C67, B8:B68) / B69 <p/>
-        */
-       public void test42448() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet1 = wb.createSheet("Sheet1");
-
-               HSSFRow row = sheet1.createRow(0);
-               HSSFCell cell = row.createCell(0);
-
-               // it's important to create the referenced sheet first
-               HSSFSheet sheet2 = wb.createSheet("A"); // note name 'A'
-               // TODO - POI crashes if the formula is added before this sheet
-               // RuntimeException("Zero length string is an invalid sheet name")
-               // Excel doesn't crash but the formula doesn't work until it is
-               // re-entered
-
-               String inputFormula = "SUMPRODUCT(A!C7:A!C67, B8:B68) / B69"; // as per bug report
-               try {
-                       cell.setCellFormula(inputFormula); 
-               } catch (StringIndexOutOfBoundsException e) {
-                       throw new AssertionFailedError("Identified bug 42448");
-               }
-
-               assertEquals("SUMPRODUCT(A!C7:A!C67,B8:B68)/B69", cell.getCellFormula());
-
-               // might as well evaluate the sucker...
-
-               addCell(sheet2, 5, 2, 3.0); // A!C6
-               addCell(sheet2, 6, 2, 4.0); // A!C7
-               addCell(sheet2, 66, 2, 5.0); // A!C67
-               addCell(sheet2, 67, 2, 6.0); // A!C68
-
-               addCell(sheet1, 6, 1, 7.0); // B7
-               addCell(sheet1, 7, 1, 8.0); // B8
-               addCell(sheet1, 67, 1, 9.0); // B68
-               addCell(sheet1, 68, 1, 10.0); // B69
-
-               double expectedResult = (4.0 * 8.0 + 5.0 * 9.0) / 10.0;
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv = fe.evaluate(cell);
-
-               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(expectedResult, cv.getNumberValue(), 0.0);
-       }
-
-       private static void addCell(HSSFSheet sheet, int rowIx, int colIx,
-                       double value) {
-               sheet.createRow(rowIx).createCell(colIx).setCellValue(value);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java
deleted file mode 100644 (file)
index 2c7c7c8..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import java.io.PrintStream;
-
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.functions.TestMathX;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-
-/**
- * Tests formulas and operators as loaded from a test data spreadsheet.<p/>
- * This class does not test implementors of <tt>Function</tt> and <tt>OperationEval</tt> in
- * isolation.  Much of the evaluation engine (i.e. <tt>HSSFFormulaEvaluator</tt>, ...) gets
- * exercised as well.  Tests for bug fixes and specific/tricky behaviour can be found in the
- * corresponding test class (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor,
- * where execution can be observed more easily.
- *
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- */
-public final class TestFormulasFromSpreadsheet extends TestCase {
-
-       private static final class Result {
-               public static final int SOME_EVALUATIONS_FAILED = -1;
-               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
-               public static final int NO_EVALUATIONS_FOUND = 0;
-       }
-
-       /**
-        * This class defines constants for navigating around the test data spreadsheet used for these tests.
-        */
-       private static final class SS {
-
-               /**
-                * Name of the test spreadsheet (found in the standard test data folder)
-                */
-               public final static String FILENAME = "FormulaEvalTestData.xls";
-               /**
-                * Row (zero-based) in the test spreadsheet where the operator examples start.
-                */
-               public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
-               /**
-                * Row (zero-based) in the test spreadsheet where the function examples start.
-                */
-               public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
-               /**
-                * Index of the column that contains the function names
-                */
-               public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
-
-               /**
-                * Used to indicate when there are no more functions left
-                */
-               public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
-
-               /**
-                * Index of the column where the test values start (for each function)
-                */
-               public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
-
-               /**
-                * Each function takes 4 rows in the test spreadsheet
-                */
-               public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
-       }
-
-       private HSSFWorkbook workbook;
-       private Sheet sheet;
-       // Note - multiple failures are aggregated before ending.
-       // If one or more functions fail, a single AssertionFailedError is thrown at the end
-       private int _functionFailureCount;
-       private int _functionSuccessCount;
-       private int _evaluationFailureCount;
-       private int _evaluationSuccessCount;
-
-       private static final Cell getExpectedValueCell(Row row, int columnIndex) {
-               if (row == null) {
-                       return null;
-               }
-               return row.getCell(columnIndex);
-       }
-
-
-       private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) {
-               if (expected == null) {
-                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
-               }
-               if(actual == null) {
-                       throw new AssertionFailedError(msg + " - actual value was null");
-               }
-
-               switch (expected.getCellType()) {
-                       case Cell.CELL_TYPE_BLANK:
-                               assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
-                               break;
-                       case Cell.CELL_TYPE_BOOLEAN:
-                               assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType());
-                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
-                               break;
-                       case Cell.CELL_TYPE_ERROR:
-                               assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType());
-                               assertEquals(msg, ErrorEval.getText(expected.getErrorCellValue()), ErrorEval.getText(actual.getErrorValue()));
-                               break;
-                       case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
-                               throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
-                       case Cell.CELL_TYPE_NUMERIC:
-                               assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
-                               TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
-                               break;
-                       case Cell.CELL_TYPE_STRING:
-                               assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
-                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
-                               break;
-               }
-       }
-
-
-       protected void setUp() {
-               if (workbook == null) {
-                       workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-                       sheet = workbook.getSheetAt( 0 );
-               }
-               _functionFailureCount = 0;
-               _functionSuccessCount = 0;
-               _evaluationFailureCount = 0;
-               _evaluationSuccessCount = 0;
-       }
-
-       public void testFunctionsFromTestSpreadsheet() {
-
-               processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
-               processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
-               // example for debugging individual functions/operators:
-//             processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
-//             processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
-
-               // confirm results
-               String successMsg = "There were "
-                               + _evaluationSuccessCount + " successful evaluation(s) and "
-                               + _functionSuccessCount + " function(s) without error";
-               if(_functionFailureCount > 0) {
-                       String msg = _functionFailureCount + " function(s) failed in "
-                       + _evaluationFailureCount + " evaluation(s).  " + successMsg;
-                       throw new AssertionFailedError(msg);
-               }
-               if(false) { // normally no output for successful tests
-                       System.out.println(getClass().getName() + ": " + successMsg);
-               }
-       }
-
-       /**
-        * @param startRowIndex row index in the spreadsheet where the first function/operator is found
-        * @param testFocusFunctionName name of a single function/operator to test alone.
-        * Typically pass <code>null</code> to test all functions
-        */
-       private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
-               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
-
-               int rowIndex = startRowIndex;
-               while (true) {
-                       Row r = sheet.getRow(rowIndex);
-                       String targetFunctionName = getTargetFunctionName(r);
-                       if(targetFunctionName == null) {
-                               throw new AssertionFailedError("Test spreadsheet cell empty on row ("
-                                               + (rowIndex+1) + "). Expected function name or '"
-                                               + SS.FUNCTION_NAMES_END_SENTINEL + "'");
-                       }
-                       if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
-                               // found end of functions list
-                               break;
-                       }
-                       if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
-
-                               // expected results are on the row below
-                               Row expectedValuesRow = sheet.getRow(rowIndex + 1);
-                               if(expectedValuesRow == null) {
-                                       int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
-                                       throw new AssertionFailedError("Missing expected values row for function '"
-                                                       + targetFunctionName + " (row " + missingRowNum + ")");
-                               }
-                               switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
-                                       case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
-                                       case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
-                                       default:
-                                               throw new RuntimeException("unexpected result");
-                                       case Result.NO_EVALUATIONS_FOUND: // do nothing
-                               }
-                       }
-                       rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
-               }
-       }
-
-       /**
-        *
-        * @return a constant from the local Result class denoting whether there were any evaluation
-        * cases, and whether they all succeeded.
-        */
-       private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName,
-                       Row formulasRow, Row expectedValuesRow) {
-
-               int result = Result.NO_EVALUATIONS_FOUND; // so far
-               short endcolnum = formulasRow.getLastCellNum();
-
-               // iterate across the row for all the evaluation cases
-               for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
-                       Cell c = formulasRow.getCell(colnum);
-                       if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
-                               continue;
-                       }
-
-                       CellValue actualValue = evaluator.evaluate(c);
-
-                       Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum);
-                       try {
-                               confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
-                                               expectedValueCell, actualValue);
-                               _evaluationSuccessCount ++;
-                               if(result != Result.SOME_EVALUATIONS_FAILED) {
-                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
-                               }
-                       } catch (AssertionFailedError e) {
-                               _evaluationFailureCount ++;
-                               printShortStackTrace(System.err, e);
-                               result = Result.SOME_EVALUATIONS_FAILED;
-                       }
-               }
-               return result;
-       }
-
-       /**
-        * Useful to keep output concise when expecting many failures to be reported by this test case
-        */
-       private static void printShortStackTrace(PrintStream ps, AssertionFailedError e) {
-               StackTraceElement[] stes = e.getStackTrace();
-
-               int startIx = 0;
-               // skip any top frames inside junit.framework.Assert
-               while(startIx<stes.length) {
-                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
-                               break;
-                       }
-                       startIx++;
-               }
-               // skip bottom frames (part of junit framework)
-               int endIx = startIx+1;
-               while(endIx < stes.length) {
-                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
-                               break;
-                       }
-                       endIx++;
-               }
-               if(startIx >= endIx) {
-                       // something went wrong. just print the whole stack trace
-                       e.printStackTrace(ps);
-               }
-               endIx -= 4; // skip 4 frames of reflection invocation
-               ps.println(e.toString());
-               for(int i=startIx; i<endIx; i++) {
-                       ps.println("\tat " + stes[i].toString());
-               }
-       }
-
-       /**
-        * @return <code>null</code> if cell is missing, empty or blank
-        */
-       private static String getTargetFunctionName(Row r) {
-               if(r == null) {
-                       System.err.println("Warning - given null row, can't figure out function name");
-                       return null;
-               }
-               Cell cell = r.getCell(SS.COLUMN_INDEX_FUNCTION_NAME);
-               if(cell == null) {
-                       System.err.println("Warning - Row " + r.getRowNum() + " has no cell " + SS.COLUMN_INDEX_FUNCTION_NAME + ", can't figure out function name");
-                       return null;
-               }
-               if(cell.getCellType() == Cell.CELL_TYPE_BLANK) {
-                       return null;
-               }
-               if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
-                       return cell.getRichStringCellValue().getString();
-               }
-
-               throw new AssertionFailedError("Bad cell type for 'function name' column: ("
-                               + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestMinusZeroResult.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestMinusZeroResult.java
deleted file mode 100644 (file)
index d2f4cc7..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.ComparisonFailure;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.functions.Function;
-import org.apache.poi.util.HexDump;
-
-/**
- * IEEE 754 defines a quantity '-0.0' which is distinct from '0.0'.
- * Negative zero is not easy to observe in Excel, since it is usually converted to 0.0.
- * (Note - the results of XLL add-in functions don't seem to be converted, so they are one
- * reliable avenue to observe Excel's treatment of '-0.0' as an operand.)
- * <p/>
- * POI attempts to emulate Excel faithfully, so this class tests
- * two aspects of '-0.0' in formula evaluation:
- * <ol>
- * <li>For most operation results '-0.0' is converted to '0.0'.</li>
- * <li>Comparison operators have slightly different rules regarding '-0.0'.</li>
- * </ol>
- * @author Josh Micich
- */
-public final class TestMinusZeroResult extends TestCase {
-       private static final double MINUS_ZERO = -0.0;
-
-       // convenient access to namepace
-       private static final EvalInstances EI = null;
-
-       public void testSimpleOperators() {
-
-               // unary plus is a no-op
-               checkEval(MINUS_ZERO, UnaryPlusEval.instance, MINUS_ZERO);
-
-               // most simple operators convert -0.0 to +0.0
-               checkEval(0.0, EI.UnaryMinus, 0.0);
-               checkEval(0.0, EI.Percent, MINUS_ZERO);
-               checkEval(0.0, EI.Multiply, MINUS_ZERO, 1.0);
-               checkEval(0.0, EI.Divide, MINUS_ZERO, 1.0);
-               checkEval(0.0, EI.Power, MINUS_ZERO, 1.0);
-
-               // but SubtractEval does not convert -0.0, so '-' and '+' work like java
-               checkEval(MINUS_ZERO, EI.Subtract, MINUS_ZERO, 0.0); // this is the main point of bug 47198
-               checkEval(0.0, EI.Add, MINUS_ZERO, 0.0);
-       }
-
-       /**
-        * These results are hard to see in Excel (since -0.0 is usually converted to +0.0 before it
-        * gets to the comparison operator)
-        */
-       public void testComparisonOperators() {
-               checkEval(false, EI.Equal, 0.0, MINUS_ZERO);
-               checkEval(true, EI.GreaterThan, 0.0, MINUS_ZERO);
-               checkEval(true, EI.LessThan, MINUS_ZERO, 0.0);
-       }
-
-       public void testTextRendering() {
-               confirmTextRendering("-0", MINUS_ZERO);
-               // sub-normal negative numbers also display as '-0'
-               confirmTextRendering("-0", Double.longBitsToDouble(0x8000100020003000L));
-       }
-
-       /**
-        * Uses {@link ConcatEval} to force number-to-text conversion
-        */
-       private static void confirmTextRendering(String expRendering, double d) {
-               ValueEval[] args = { StringEval.EMPTY_INSTANCE, new NumberEval(d), };
-               StringEval se = (StringEval) EI.Concat.evaluate(args, -1, (short)-1);
-               String result = se.getStringValue();
-               assertEquals(expRendering, result);
-       }
-
-       private static void checkEval(double expectedResult, Function instance, double... dArgs) {
-               NumberEval result = (NumberEval) evaluate(instance, dArgs);
-               assertDouble(expectedResult, result.getNumberValue());
-       }
-       private static void checkEval(boolean expectedResult, Function instance, double... dArgs) {
-               BoolEval result = (BoolEval) evaluate(instance, dArgs);
-               assertEquals(expectedResult, result.getBooleanValue());
-       }
-       private static ValueEval evaluate(Function instance, double... dArgs) {
-               ValueEval[] evalArgs;
-               evalArgs = new ValueEval[dArgs.length];
-               for (int i = 0; i < evalArgs.length; i++) {
-                       evalArgs[i] = new NumberEval(dArgs[i]);
-               }
-               ValueEval r = instance.evaluate(evalArgs, -1, (short)-1);
-               return r;
-       }
-
-       /**
-        * Not really a POI test - just shows similar behaviour of '-0.0' in Java.
-        */
-       public void testJava() {
-
-               assertEquals(0x8000000000000000L, Double.doubleToLongBits(MINUS_ZERO));
-
-               // The simple operators consider all zeros to be the same
-               assertTrue(MINUS_ZERO == MINUS_ZERO);
-               assertTrue(MINUS_ZERO == +0.0);
-               assertFalse(MINUS_ZERO < +0.0);
-
-               // Double.compare() considers them different
-               assertTrue(Double.compare(MINUS_ZERO, +0.0) < 0);
-
-               // multiplying zero by any negative quantity yields minus zero
-               assertDouble(MINUS_ZERO, 0.0*-1);
-               assertDouble(MINUS_ZERO, 0.0*-1e300);
-               assertDouble(MINUS_ZERO, 0.0*-1e-300);
-
-               // minus zero can be produced as a result of underflow
-               assertDouble(MINUS_ZERO, -1e-300 / 1e100);
-
-               // multiplying or dividing minus zero by a positive quantity yields minus zero
-               assertDouble(MINUS_ZERO, MINUS_ZERO * 1.0);
-               assertDouble(MINUS_ZERO, MINUS_ZERO / 1.0);
-
-               // subtracting positive zero gives minus zero
-               assertDouble(MINUS_ZERO, MINUS_ZERO - 0.0);
-               // BUT adding positive zero gives positive zero
-               assertDouble(0.0, MINUS_ZERO + 0.0);  // <<----
-       }
-
-       /**
-        * Just so there is no ambiguity.  The two double values have to be exactly equal
-        */
-       private static void assertDouble(double a, double b) {
-               long bitsA = Double.doubleToLongBits(a);
-               long bitsB = Double.doubleToLongBits(b);
-               if (bitsA != bitsB) {
-                       throw new ComparisonFailure("value different to expected",
-                                       new String(HexDump.longToHex(bitsA)), new String(HexDump.longToHex(bitsB)));
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestMissingArgEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestMissingArgEval.java
deleted file mode 100644 (file)
index 2a830b0..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import java.util.EmptyStackException;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Tests for {@link MissingArgEval}
- *
- * @author Josh Micich
- */
-public final class TestMissingArgEval extends TestCase {
-       
-       public void testEvaluateMissingArgs() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-               HSSFCell cell = sheet.createRow(0).createCell(0);
-               
-               cell.setCellFormula("if(true,)"); 
-               fe.clearAllCachedResultValues();
-               CellValue cv;
-               try {
-                       cv = fe.evaluate(cell);
-               } catch (EmptyStackException e) {
-                       throw new AssertionFailedError("Missing args evaluation not implemented (bug 43354");
-               }
-               // MissingArg -> BlankEval -> zero (as formula result)
-               assertEquals(0.0, cv.getNumberValue(), 0.0);
-               
-               // MissingArg -> BlankEval -> empty string (in concatenation)
-               cell.setCellFormula("\"abc\"&if(true,)"); 
-               fe.clearAllCachedResultValues();
-               assertEquals("abc", fe.evaluate(cell).getStringValue());
-       }
-       
-       public void testCountFuncs() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-               HSSFCell cell = sheet.createRow(0).createCell(0);
-               
-               cell.setCellFormula("COUNT(C5,,,,)"); // 4 missing args, C5 is blank 
-               assertEquals(4.0, fe.evaluate(cell).getNumberValue(), 0.0);
-
-               cell.setCellFormula("COUNTA(C5,,)"); // 2 missing args, C5 is blank 
-               fe.clearAllCachedResultValues();
-               assertEquals(2.0, fe.evaluate(cell).getNumberValue(), 0.0);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestOperandResolver.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestOperandResolver.java
deleted file mode 100644 (file)
index 98ddade..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-/**
- * Tests for <tt>OperandResolver</tt>
- *
- * @author Brendan Nolan
- */
-public final class TestOperandResolver extends TestCase {
-
-       public void testParseDouble_bug48472() {
-               
-               String value = "-";
-               
-               Double resolvedValue = null;
-               
-               try {
-                       resolvedValue = OperandResolver.parseDouble(value);
-               } catch (StringIndexOutOfBoundsException e) { 
-                       throw new AssertionFailedError("Identified bug 48472");
-               }
-               
-               assertEquals(null, resolvedValue);
-               
-       }
-       
-       public void testParseDouble_bug49723() {
-               
-               String value = ".1";
-               
-               Double resolvedValue = null;
-               
-               resolvedValue = OperandResolver.parseDouble(value);
-               
-               assertNotNull("Identified bug 49723", resolvedValue);
-               
-       }
-       
-       /**
-        * 
-        * Tests that a list of valid strings all return a non null value from {@link OperandResolver#parseDouble(String)}
-        * 
-        */
-       public void testParseDoubleValidStrings() {
-                               
-               String[] values = new String[]{".19", "0.19", "1.9", "1E4", "-.19", "-0.19", "8.5","-1E4", ".5E6","+1.5","+1E5", "  +1E5  "};
-               
-               for (String value : values) {
-                       assertTrue(OperandResolver.parseDouble(value) != null);
-                       assertEquals(OperandResolver.parseDouble(value), Double.parseDouble(value));
-               }
-
-       }
-       
-       /**
-        * 
-        * Tests that a list of invalid strings all return null from {@link OperandResolver#parseDouble(String)}
-        * 
-        */
-       public void testParseDoubleInvalidStrings() {
-               
-               String[] values = new String[]{"-", "ABC", "-X", "1E5a", "Infinity", "NaN", ".5F", "1,000"};
-               
-               for (String value : values) {
-                       assertEquals(null, OperandResolver.parseDouble(value));
-               }
-
-       }
-       
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java
deleted file mode 100644 (file)
index ae6524e..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.functions.EvalFactory;
-import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Test for percent operator evaluator.
- *
- * @author Josh Micich
- */
-public final class TestPercentEval extends TestCase {
-
-       private static void confirm(ValueEval arg, double expectedResult) {
-               ValueEval[] args = {
-                       arg,
-               };
-
-               double result = NumericFunctionInvoker.invoke(PercentEval.instance, args, 0, 0);
-
-               assertEquals(expectedResult, result, 0);
-       }
-
-       public void testBasic() {
-               confirm(new NumberEval(5), 0.05);
-               confirm(new NumberEval(3000), 30.0);
-               confirm(new NumberEval(-150), -1.5);
-               confirm(new StringEval("0.2"), 0.002);
-               confirm(BoolEval.TRUE, 0.01);
-       }
-
-       public void test1x1Area() {
-               AreaEval ae = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
-               confirm(ae, 0.5);
-       }
-       public void testInSpreadSheet() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-               HSSFRow row = sheet.createRow(0);
-               HSSFCell cell = row.createCell(0);
-               cell.setCellFormula("B1%");
-               row.createCell(1).setCellValue(50.0);
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv;
-               try {
-                       cv = fe.evaluate(cell);
-               } catch (RuntimeException e) {
-                       if(e.getCause() instanceof NullPointerException) {
-                               throw new AssertionFailedError("Identified bug 44608");
-                       }
-                       // else some other unexpected error
-                       throw e;
-               }
-               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
-               assertEquals(0.5, cv.getNumberValue(), 0.0);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java
deleted file mode 100644 (file)
index 80af1b9..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.AreaI;
-import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.AreaReference;
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.ss.formula.TwoDEval;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Test for unary plus operator evaluator.
- *
- * @author Josh Micich
- */
-public final class TestRangeEval extends TestCase {
-
-       public void testPermutations() {
-
-               confirm("B3", "D7", "B3:D7");
-               confirm("B1", "B1", "B1:B1");
-
-               confirm("B7", "D3", "B3:D7");
-               confirm("D3", "B7", "B3:D7");
-               confirm("D7", "B3", "B3:D7");
-       }
-
-       private static void confirm(String refA, String refB, String expectedAreaRef) {
-
-               ValueEval[] args = {
-                       createRefEval(refA),
-                       createRefEval(refB),
-               };
-               AreaReference ar = new AreaReference(expectedAreaRef);
-               ValueEval result = EvalInstances.Range.evaluate(args, 0, (short)0);
-               assertTrue(result instanceof AreaEval);
-               AreaEval ae = (AreaEval) result;
-               assertEquals(ar.getFirstCell().getRow(), ae.getFirstRow());
-               assertEquals(ar.getLastCell().getRow(), ae.getLastRow());
-               assertEquals(ar.getFirstCell().getCol(), ae.getFirstColumn());
-               assertEquals(ar.getLastCell().getCol(), ae.getLastColumn());
-       }
-
-       private static ValueEval createRefEval(String refStr) {
-               CellReference cr = new CellReference(refStr);
-               return new MockRefEval(cr.getRow(), cr.getCol());
-
-       }
-
-       private static final class MockRefEval extends RefEvalBase {
-
-               public MockRefEval(int rowIndex, int columnIndex) {
-                       super(rowIndex, columnIndex);
-               }
-               public ValueEval getInnerValueEval() {
-                       throw new RuntimeException("not expected to be called during this test");
-               }
-               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
-                               int relLastColIx) {
-                       AreaI area = new OffsetArea(getRow(), getColumn(),
-                                       relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-                       return new MockAreaEval(area);
-               }
-       }
-
-       private static final class MockAreaEval extends AreaEvalBase {
-
-               public MockAreaEval(AreaI ptg) {
-                       super(ptg);
-               }
-               private MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn) {
-                       super(firstRow, firstColumn, lastRow, lastColumn);
-               }
-               public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
-                       throw new RuntimeException("not expected to be called during this test");
-               }
-               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
-                               int relLastColIx) {
-                       AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
-                                       relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-
-                       return new MockAreaEval(area);
-               }
-               public TwoDEval getRow(int rowIndex) {
-                       if (rowIndex >= getHeight()) {
-                               throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
-                                               + ".  Allowable range is (0.." + getHeight() + ").");
-                       }
-                       return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn());
-               }
-               public TwoDEval getColumn(int columnIndex) {
-                       if (columnIndex >= getWidth()) {
-                               throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
-                                               + ".  Allowable range is (0.." + getWidth() + ").");
-                       }
-                       return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex);
-               }
-       }
-
-       public void testRangeUsingOffsetFunc_bug46948() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFRow row = wb.createSheet("Sheet1").createRow(0);
-               HSSFCell cellA1 = row.createCell(0);
-               HSSFCell cellB1 = row.createCell(1);
-               row.createCell(2).setCellValue(5.0); // C1
-               row.createCell(3).setCellValue(7.0); // D1
-               row.createCell(4).setCellValue(9.0); // E1
-
-
-               cellA1.setCellFormula("SUM(C1:OFFSET(C1,0,B1))");
-
-               cellB1.setCellValue(1.0); // range will be C1:D1
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               CellValue cv;
-               try {
-                       cv = fe.evaluate(cellA1);
-               } catch (IllegalArgumentException e) {
-                       if (e.getMessage().equals("Unexpected ref arg class (org.apache.poi.ss.formula.LazyAreaEval)")) {
-                               throw new AssertionFailedError("Identified bug 46948");
-                       }
-                       throw e;
-               }
-
-               assertEquals(12.0, cv.getNumberValue(), 0.0);
-
-               cellB1.setCellValue(2.0); // range will be C1:E1
-               fe.notifyUpdateCell(cellB1);
-               cv = fe.evaluate(cellA1);
-               assertEquals(21.0, cv.getNumberValue(), 0.0);
-
-               cellB1.setCellValue(0.0); // range will be C1:C1
-               fe.notifyUpdateCell(cellB1);
-               cv = fe.evaluate(cellA1);
-               assertEquals(5.0, cv.getNumberValue(), 0.0);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java
deleted file mode 100644 (file)
index ffa42b3..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.eval;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.AreaPtg;
-import org.apache.poi.hssf.record.formula.functions.EvalFactory;
-import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
-
-/**
- * Test for unary plus operator evaluator.
- *
- * @author Josh Micich
- */
-public final class TestUnaryPlusEval extends TestCase {
-
-       /**
-        * Test for bug observable at svn revision 618865 (5-Feb-2008)<br/>
-        * The code for handling column operands had been copy-pasted from the row handling code.
-        */
-       public void testColumnOperand() {
-
-               short firstRow = (short)8;
-               short lastRow = (short)12;
-               short colNum = (short)5;
-               AreaPtg areaPtg = new AreaPtg(firstRow, lastRow, colNum, colNum, false, false, false, false);
-               ValueEval[] values = {
-                               new NumberEval(27),
-                               new NumberEval(29),
-                               new NumberEval(35),     // value in row 10
-                               new NumberEval(37),
-                               new NumberEval(38),
-               };
-               ValueEval[] args = {
-                       EvalFactory.createAreaEval(areaPtg, values),
-               };
-
-               double result = NumericFunctionInvoker.invoke(EvalInstances.UnaryPlus, args, 10, (short)20);
-
-               assertEquals(35, result, 0);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/AllFormulaFunctionTests.java b/src/testcases/org/apache/poi/hssf/record/formula/function/AllFormulaFunctionTests.java
deleted file mode 100644 (file)
index 01f88bd..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.function;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-/**
- * Collects all tests for this <tt>org.apache.poi.hssf.record.formula.function</tt>.
- * 
- * @author Josh Micich
- */
-public class AllFormulaFunctionTests {
-       
-       public static Test suite() {
-               TestSuite result = new TestSuite(AllFormulaFunctionTests.class.getName());
-               result.addTestSuite(TestFunctionMetadataRegistry.class);
-               result.addTestSuite(TestParseMissingBuiltInFuncs.class);
-               result.addTestSuite(TestReadMissingBuiltInFuncs.class);
-               return result;
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/ExcelFileFormatDocFunctionExtractor.java b/src/testcases/org/apache/poi/hssf/record/formula/function/ExcelFileFormatDocFunctionExtractor.java
deleted file mode 100644 (file)
index c3a026c..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.function;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- * This class is not used during normal POI run-time but is used at development time to generate
- * the file 'functionMetadata.txt'.   There are more than 300 built-in functions in Excel and the
- * intention of this class is to make it easier to maintain the metadata, by extracting it from
- * a reliable source.
- *
- * @author Josh Micich
- */
-public final class ExcelFileFormatDocFunctionExtractor {
-
-       private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
-
-       /**
-        * For simplicity, the output file is strictly simple ASCII.
-        * This method detects any unexpected characters.
-        */
-       /* package */ static boolean isSimpleAscii(char c) {
-
-               if (c>=0x21 && c<=0x7E) {
-                       // everything from '!' to '~' (includes letters, digits, punctuation
-                       return true;
-               }
-               // some specific whitespace chars below 0x21:
-               switch(c) {
-                       case ' ':
-                       case '\t':
-                       case '\r':
-                       case '\n':
-                               return true;
-               }
-               return false;
-       }
-
-
-       private static final class FunctionData {
-               // special characters from the ooo document
-               private static final int CHAR_ELLIPSIS_8230 = 8230;
-               private static final int CHAR_NDASH_8211 = 8211;
-
-               private final int _index;
-               private final boolean _hasFootnote;
-               private final String _name;
-               private final int _minParams;
-               private final int _maxParams;
-               private final String _returnClass;
-               private final String _paramClasses;
-               private final boolean _isVolatile;
-
-               public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
-                                       String returnClass, String paramClasses, boolean isVolatile) {
-                       _index = funcIx;
-                       _hasFootnote = hasFootnote;
-                       _name = funcName;
-                       _minParams = minParams;
-                       _maxParams = maxParams;
-                       _returnClass = convertSpecialChars(returnClass);
-                       _paramClasses = convertSpecialChars(paramClasses);
-                       _isVolatile = isVolatile;
-               }
-               private static String convertSpecialChars(String ss) {
-                       StringBuffer sb = new StringBuffer(ss.length() + 4);
-                       for(int i=0; i<ss.length(); i++) {
-                               char c = ss.charAt(i);
-                               if (isSimpleAscii(c)) {
-                                       sb.append(c);
-                                       continue;
-                               }
-                               switch (c) {
-                                       case CHAR_NDASH_8211:
-                                               sb.append('-');
-                                               continue;
-                                       case CHAR_ELLIPSIS_8230:
-                                               sb.append("...");
-                                               continue;
-                               }
-                               throw new RuntimeException("bad char (" + ((int)c) + ") in string '" + ss + "'");
-                       }
-                       return sb.toString();
-               }
-               public int getIndex() {
-                       return _index;
-               }
-               public String getName() {
-                       return _name;
-               }
-               public boolean hasFootnote() {
-                       return _hasFootnote;
-               }
-               public String formatAsDataLine() {
-                       return _index + "\t" + _name + "\t" + _minParams + "\t"
-                                       + _maxParams + "\t" + _returnClass + "\t" + _paramClasses
-                                       + "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote);
-               }
-               private static String checkMark(boolean b) {
-                       return b ? "x" : "";
-               }
-       }
-
-       private static final class FunctionDataCollector {
-
-               private final Map _allFunctionsByIndex;
-               private final Map _allFunctionsByName;
-               private final Set _groupFunctionIndexes;
-               private final Set _groupFunctionNames;
-               private final PrintStream _ps;
-
-               public FunctionDataCollector(PrintStream ps) {
-                       _ps = ps;
-                       _allFunctionsByIndex = new HashMap();
-                       _allFunctionsByName = new HashMap();
-                       _groupFunctionIndexes = new HashSet();
-                       _groupFunctionNames = new HashSet();
-               }
-
-               public void addFuntion(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
-                               String returnClass, String paramClasses, String volatileFlagStr) {
-                       boolean isVolatile = volatileFlagStr.length() > 0;
-
-                       Integer funcIxKey = Integer.valueOf(funcIx);
-                       if(!_groupFunctionIndexes.add(funcIxKey)) {
-                               throw new RuntimeException("Duplicate function index (" + funcIx + ")");
-                       }
-                       if(!_groupFunctionNames.add(funcName)) {
-                               throw new RuntimeException("Duplicate function name '" + funcName + "'");
-                       }
-
-                       checkRedefinedFunction(hasFootnote, funcName, funcIxKey);
-                       FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName,
-                                       minParams, maxParams, returnClass, paramClasses, isVolatile);
-
-                       _allFunctionsByIndex.put(funcIxKey, fd);
-                       _allFunctionsByName.put(funcName, fd);
-               }
-
-               /**
-                * Some extra validation here.
-                * Any function which changes definition will have a footnote in the source document
-                */
-               private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) {
-                       FunctionData fdPrev;
-                       // check by index
-                       fdPrev = (FunctionData) _allFunctionsByIndex.get(funcIxKey);
-                       if(fdPrev != null) {
-                               if(!fdPrev.hasFootnote() || !hasNote) {
-                                       throw new RuntimeException("changing function ["
-                                                       + funcIxKey + "] definition without foot-note");
-                               }
-                               _allFunctionsByName.remove(fdPrev.getName());
-                       }
-                       // check by name
-                       fdPrev = (FunctionData) _allFunctionsByName.get(funcName);
-                       if(fdPrev != null) {
-                               if(!fdPrev.hasFootnote() || !hasNote) {
-                                       throw new RuntimeException("changing function '"
-                                                       + funcName + "' definition without foot-note");
-                               }
-                               _allFunctionsByIndex.remove(Integer.valueOf(fdPrev.getIndex()));
-                       }
-               }
-
-               public void endTableGroup(String headingText) {
-                       Integer[] keys = new Integer[_groupFunctionIndexes.size()];
-                       _groupFunctionIndexes.toArray(keys);
-                       _groupFunctionIndexes.clear();
-                       _groupFunctionNames.clear();
-                       Arrays.sort(keys);
-
-                       _ps.println("# " + headingText);
-                       for (int i = 0; i < keys.length; i++) {
-                               FunctionData fd = (FunctionData) _allFunctionsByIndex.get(keys[i]);
-                               _ps.println(fd.formatAsDataLine());
-                       }
-               }
-       }
-
-       /**
-        * To avoid drag-in - parse XML using only JDK.
-        */
-       private static class EFFDocHandler implements ContentHandler {
-               private static final String[] HEADING_PATH_NAMES = {
-                       "office:document-content", "office:body", "office:text", "text:h",
-               };
-               private static final String[] TABLE_BASE_PATH_NAMES = {
-                       "office:document-content", "office:body", "office:text", "table:table",
-               };
-               private static final String[] TABLE_ROW_RELPATH_NAMES = {
-                       "table:table-row",
-               };
-               private static final String[] TABLE_CELL_RELPATH_NAMES = {
-                       "table:table-row", "table:table-cell", "text:p",
-               };
-               // after May 2008 there was one more style applied to the footnotes
-               private static final String[] NOTE_REF_RELPATH_NAMES_OLD = {
-                       "table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
-               };
-               private static final String[] NOTE_REF_RELPATH_NAMES = {
-                       "table:table-row", "table:table-cell", "text:p", "text:span", "text:span", "text:note-ref",
-               };
-
-
-               private final Stack _elemNameStack;
-               /** <code>true</code> only when parsing the target tables */
-               private boolean _isInsideTable;
-
-               private final List _rowData;
-               private final StringBuffer _textNodeBuffer;
-               private final List _rowNoteFlags;
-               private boolean _cellHasNote;
-
-               private final FunctionDataCollector _fdc;
-               private String _lastHeadingText;
-
-               public EFFDocHandler(FunctionDataCollector fdc) {
-                       _fdc = fdc;
-                       _elemNameStack = new Stack();
-                       _isInsideTable = false;
-                       _rowData = new ArrayList();
-                       _textNodeBuffer = new StringBuffer();
-                       _rowNoteFlags = new ArrayList();
-               }
-
-               private boolean matchesTargetPath() {
-                       return matchesPath(0, TABLE_BASE_PATH_NAMES);
-               }
-               private boolean matchesRelPath(String[] pathNames) {
-                       return matchesPath(TABLE_BASE_PATH_NAMES.length, pathNames);
-               }
-               private boolean matchesPath(int baseStackIndex, String[] pathNames) {
-                       if(_elemNameStack.size() != baseStackIndex + pathNames.length) {
-                               return false;
-                       }
-                       for (int i = 0; i < pathNames.length; i++) {
-                               if(!_elemNameStack.get(baseStackIndex + i).equals(pathNames[i])) {
-                                       return false;
-                               }
-                       }
-                       return true;
-               }
-               public void characters(char[] ch, int start, int length) {
-                       // only 2 text nodes where text is collected:
-                       if(matchesRelPath(TABLE_CELL_RELPATH_NAMES) || matchesPath(0, HEADING_PATH_NAMES)) {
-                               _textNodeBuffer.append(ch, start, length);
-                       }
-               }
-
-               public void endElement(String namespaceURI, String localName, String name) {
-                       String expectedName = (String) _elemNameStack.peek();
-                       if(expectedName != name) {
-                               throw new RuntimeException("close tag mismatch");
-                       }
-                       if(matchesPath(0, HEADING_PATH_NAMES)) {
-                               _lastHeadingText = _textNodeBuffer.toString().trim();
-                               _textNodeBuffer.setLength(0);
-                       }
-                       if(_isInsideTable) {
-                               if(matchesTargetPath()) {
-                                       _fdc.endTableGroup(_lastHeadingText);
-                                       _isInsideTable = false;
-                               } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
-                                       String[] cellData = new String[_rowData.size()];
-                                       _rowData.toArray(cellData);
-                                       _rowData.clear();
-                                       Boolean[] noteFlags = new Boolean[_rowNoteFlags.size()];
-                                       _rowNoteFlags.toArray(noteFlags);
-                                       _rowNoteFlags.clear();
-                                       processTableRow(cellData, noteFlags);
-                               } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
-                                       _rowData.add(_textNodeBuffer.toString().trim());
-                                       _rowNoteFlags.add(Boolean.valueOf(_cellHasNote));
-                                       _textNodeBuffer.setLength(0);
-                               }
-                       }
-                       _elemNameStack.pop();
-               }
-
-               private void processTableRow(String[] cellData, Boolean[] noteFlags) {
-                       // each table row of the document contains data for two functions
-                       if(cellData.length != 15) {
-                               throw new RuntimeException("Bad table row size");
-                       }
-                       processFunction(cellData, noteFlags, 0);
-                       processFunction(cellData, noteFlags, 8);
-               }
-               public void processFunction(String[] cellData, Boolean[] noteFlags, int i) {
-                       String funcIxStr = cellData[i + 0];
-                       if (funcIxStr.length() < 1) {
-                               // empty (happens on the right hand side when there is an odd number of functions)
-                               return;
-                       }
-                       int funcIx = parseInt(funcIxStr);
-
-                       boolean hasFootnote = noteFlags[i + 1].booleanValue();
-                       String funcName = cellData[i + 1];
-                       int minParams = parseInt(cellData[i + 2]);
-                       int maxParams = parseInt(cellData[i + 3]);
-
-                       String returnClass = cellData[i + 4];
-                       String paramClasses = cellData[i + 5];
-                       String volatileFlagStr = cellData[i + 6];
-
-                       _fdc.addFuntion(funcIx, hasFootnote, funcName, minParams, maxParams, returnClass, paramClasses, volatileFlagStr);
-               }
-               private static int parseInt(String valStr) {
-                       try {
-                               return Integer.parseInt(valStr);
-                       } catch (NumberFormatException e) {
-                               throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
-                       }
-               }
-               public void startElement(String namespaceURI, String localName, String name, Attributes atts) {
-                       _elemNameStack.add(name);
-                       if(matchesTargetPath()) {
-                               String tableName = atts.getValue("table:name");
-                               if(tableName.startsWith("tab_fml_func") && !tableName.equals("tab_fml_func0")) {
-                                       _isInsideTable = true;
-                               }
-                               return;
-                       }
-                       if(matchesPath(0, HEADING_PATH_NAMES)) {
-                               _textNodeBuffer.setLength(0);
-                       } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
-                               _rowData.clear();
-                               _rowNoteFlags.clear();
-                       } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
-                               _textNodeBuffer.setLength(0);
-                               _cellHasNote = false;
-                       } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES_OLD)) {
-                               _cellHasNote = true;
-                       } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) {
-                               _cellHasNote = true;
-                       }
-               }
-
-               public void endDocument() {
-                       // do nothing
-               }
-               public void endPrefixMapping(String prefix) {
-                       // do nothing
-               }
-               public void ignorableWhitespace(char[] ch, int start, int length) {
-                       // do nothing
-               }
-               public void processingInstruction(String target, String data) {
-                       // do nothing
-               }
-               public void setDocumentLocator(Locator locator) {
-                       // do nothing
-               }
-               public void skippedEntity(String name) {
-                       // do nothing
-               }
-               public void startDocument() {
-                       // do nothing
-               }
-               public void startPrefixMapping(String prefix, String uri) {
-                       // do nothing
-               }
-       }
-
-       private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) {
-               XMLReader xr;
-
-               try {
-                       // First up, try the default one
-                       xr = XMLReaderFactory.createXMLReader();
-               } catch (SAXException e) {
-                       // Try one for java 1.4
-                       System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
-                       try {
-                               xr = XMLReaderFactory.createXMLReader();
-                       } catch (SAXException e2) {
-                               throw new RuntimeException(e2);
-                       }
-               }
-               xr.setContentHandler(new EFFDocHandler(fdc));
-
-               InputSource inSrc = new InputSource(is);
-
-               try {
-                       xr.parse(inSrc);
-                       is.close();
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               } catch (SAXException e) {
-                       throw new RuntimeException(e);
-               }
-       }
-       /**
-        * To be sure that no tricky unicode chars make it through to the output file.
-        */
-       private static final class SimpleAsciiOutputStream extends OutputStream {
-
-               private final OutputStream _os;
-
-               public SimpleAsciiOutputStream(OutputStream os) {
-                       _os = os;
-               }
-               public void write(int b) throws IOException {
-                       checkByte(b);
-                       _os.write(b);
-               }
-               private static void checkByte(int b) {
-                       if (!isSimpleAscii((char)b)) {
-                               throw new RuntimeException("Encountered char (" + b + ") which was not simple ascii as expected");
-                       }
-               }
-               public void write(byte[] b, int off, int len) throws IOException {
-                       for (int i = 0; i < len; i++) {
-                               checkByte(b[i + off]);
-
-                       }
-                       _os.write(b, off, len);
-               }
-       }
-
-       private static void processFile(File effDocFile, File outFile) {
-               if(!effDocFile.exists()) {
-                       throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
-               }
-               OutputStream os;
-               try {
-                       os = new FileOutputStream(outFile);
-               } catch (FileNotFoundException e) {
-                       throw new RuntimeException(e);
-               }
-               os = new SimpleAsciiOutputStream(os);
-               PrintStream ps;
-               try {
-                       ps = new PrintStream(os, true, "UTF-8");
-               } catch(UnsupportedEncodingException e) {
-                       throw new RuntimeException(e);
-               }
-
-               outputLicenseHeader(ps);
-               Class genClass = ExcelFileFormatDocFunctionExtractor.class;
-               ps.println("# Created by (" + genClass.getName() + ")");
-               // identify the source file
-               ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'");
-               ps.println(" (size=" + effDocFile.length() + ", md5=" + getFileMD5(effDocFile) + ")");
-               ps.println("#");
-               ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )");
-               ps.println("");
-               try {
-                       ZipFile zf = new ZipFile(effDocFile);
-                       InputStream is = zf.getInputStream(zf.getEntry("content.xml"));
-                       extractFunctionData(new FunctionDataCollector(ps), is);
-                       zf.close();
-               } catch (ZipException e) {
-                       throw new RuntimeException(e);
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               }
-               ps.close();
-
-               String canonicalOutputFileName;
-               try {
-                       canonicalOutputFileName = outFile.getCanonicalPath();
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               }
-               System.out.println("Successfully output to '" + canonicalOutputFileName + "'");
-       }
-
-       private static void outputLicenseHeader(PrintStream ps) {
-               String[] lines= {
-                       "Licensed to the Apache Software Foundation (ASF) under one or more",
-                       "contributor license agreements.  See the NOTICE file distributed with",
-                       "this work for additional information regarding copyright ownership.",
-                       "The ASF licenses this file to You 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.",
-               };
-               for (int i = 0; i < lines.length; i++) {
-                       ps.print("# ");
-                       ps.println(lines[i]);
-               }
-               ps.println();
-       }
-
-       /**
-        * Helps identify the source file
-        */
-       private static String getFileMD5(File f) {
-               MessageDigest m;
-               try {
-                       m = MessageDigest.getInstance("MD5");
-               } catch (NoSuchAlgorithmException e) {
-                       throw new RuntimeException(e);
-               }
-
-               byte[]buf = new byte[2048];
-               try {
-                       InputStream is = new FileInputStream(f);
-                       while(true) {
-                               int bytesRead = is.read(buf);
-                               if(bytesRead<1) {
-                                       break;
-                               }
-                               m.update(buf, 0, bytesRead);
-                       }
-                       is.close();
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               }
-
-               return "0x" + new BigInteger(1, m.digest()).toString(16);
-       }
-
-       private static File downloadSourceFile() {
-               URL url;
-               try {
-                       url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME);
-               } catch (MalformedURLException e) {
-                       throw new RuntimeException(e);
-               }
-
-               File result;
-               byte[]buf = new byte[2048];
-               try {
-                       URLConnection conn = url.openConnection();
-                       InputStream is = conn.getInputStream();
-                       System.out.println("downloading " + url.toExternalForm());
-                       result = File.createTempFile("excelfileformat", ".odt");
-                       OutputStream os = new FileOutputStream(result);
-                       while(true) {
-                               int bytesRead = is.read(buf);
-                               if(bytesRead<1) {
-                                       break;
-                               }
-                               os.write(buf, 0, bytesRead);
-                       }
-                       is.close();
-                       os.close();
-               } catch (IOException e) {
-                       throw new RuntimeException(e);
-               }
-               System.out.println("file downloaded ok");
-               return result;
-       }
-
-       public static void main(String[] args) {
-
-               File outFile = new File("functionMetadata-asGenerated.txt");
-
-               if (false) { // set true to use local file
-                       File dir = new File("c:/temp");
-                       File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
-                       processFile(effDocFile, outFile);
-                       return;
-               }
-
-               File tempEFFDocFile = downloadSourceFile();
-               processFile(tempEFFDocFile, outFile);
-               tempEFFDocFile.delete();
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/TestFunctionMetadataRegistry.java b/src/testcases/org/apache/poi/hssf/record/formula/function/TestFunctionMetadataRegistry.java
deleted file mode 100644 (file)
index c175c47..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.function;
-
-import junit.framework.TestCase;
-
-/**
- * 
- * @author Josh Micich
- */
-public final class TestFunctionMetadataRegistry extends TestCase {
-
-       public void testWellKnownFunctions() {
-               confirmFunction(0, "COUNT");
-               confirmFunction(1, "IF");
-
-       }
-
-       private static void confirmFunction(int index, String funcName) {
-               FunctionMetadata fm;
-               fm = FunctionMetadataRegistry.getFunctionByIndex(index);
-               assertNotNull(fm);
-               assertEquals(funcName, fm.getName());
-
-               fm = FunctionMetadataRegistry.getFunctionByName(funcName);
-               assertNotNull(fm);
-               assertEquals(index, fm.getIndex());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/function/TestParseMissingBuiltInFuncs.java
deleted file mode 100644 (file)
index 95ad2ef..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.function;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
-import org.apache.poi.hssf.record.formula.FuncPtg;
-import org.apache.poi.hssf.record.formula.FuncVarPtg;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-/**
- * Tests parsing of some built-in functions that were not properly
- * registered in POI as of bug #44675, #44733 (March/April 2008).
- * 
- * @author Josh Micich
- */
-public final class TestParseMissingBuiltInFuncs extends TestCase {
-
-       private static Ptg[] parse(String formula) {
-               HSSFWorkbook book = new HSSFWorkbook();
-               return HSSFFormulaParser.parse(formula, book);
-       }
-       private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) {
-               Ptg[] ptgs = parse(formula);
-               Ptg ptgF = ptgs[ptgs.length-1];  // func is last RPN token in all these formulas
-               
-               // Check critical things in the Ptg array encoding.
-               if(!(ptgF instanceof AbstractFunctionPtg)) {
-                   throw new RuntimeException("function token missing");
-               }
-               AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
-               if(func.getFunctionIndex() == 255) {
-                       throw new AssertionFailedError("Failed to recognise built-in function in formula '" 
-                                       + formula + "'");
-               }
-               assertEquals(expPtgArraySize, ptgs.length);
-               assertEquals(funcIx, func.getFunctionIndex());
-               Class expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class;
-               assertEquals(expCls, ptgF.getClass());
-               
-               // check that parsed Ptg array converts back to formula text OK
-               HSSFWorkbook book = new HSSFWorkbook();
-               String reRenderedFormula = HSSFFormulaParser.toFormulaString(book, ptgs);
-               assertEquals(formula, reRenderedFormula);
-       }
-       
-       public void testDatedif() {
-               int expSize = 4;   // NB would be 5 if POI added tAttrVolatile properly
-               confirmFunc("DATEDIF(NOW(),NOW(),\"d\")", expSize, false, 351);
-       }
-
-       public void testDdb() {
-               confirmFunc("DDB(1,1,1,1,1)", 6, true, 144);
-       }
-       public void testAtan() {
-               confirmFunc("ATAN(1)", 2, false, 18);
-       }
-       
-       public void testUsdollar() {
-               confirmFunc("USDOLLAR(1)", 2, true, 204);
-       }
-
-       public void testDBCS() {
-               confirmFunc("DBCS(\"abc\")", 2, false, 215);
-       }
-       public void testIsnontext() {
-               confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190);
-       }
-       public void testDproduct() {
-               confirmFunc("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", 4, false, 189);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/function/TestReadMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/function/TestReadMissingBuiltInFuncs.java
deleted file mode 100644 (file)
index 5d8ccc7..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.function;
-
-import java.lang.reflect.InvocationTargetException;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.RecordFormatException;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-/**
- * Tests reading from a sample spreadsheet some built-in functions that were not properly
- * registered in POI as of bug #44675, #44733 (March/April 2008).
- * 
- * @author Josh Micich
- */
-public final class TestReadMissingBuiltInFuncs extends TestCase {
-
-       /**
-        * This spreadsheet has examples of calls to the interesting built-in functions in cells A1:A7
-        */
-       private static final String SAMPLE_SPREADSHEET_FILE_NAME = "missingFuncs44675.xls";
-       private static HSSFSheet _sheet;
-
-       private static HSSFSheet getSheet() {
-               if (_sheet == null) {
-                       HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_SPREADSHEET_FILE_NAME);
-                       _sheet = wb.getSheetAt(0);
-               }
-               return _sheet;
-       }
-
-       public void testDatedif() {
-               
-               String formula;
-               try {
-                       formula = getCellFormula(0);
-               } catch (IllegalStateException e) {
-                       if(e.getMessage().startsWith("Too few arguments")) {
-                               if(e.getMessage().indexOf("AttrPtg") > 0) {
-                                       throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
-                               }
-                               throw afe("NOW() registered with 1 arg instead of 0");
-                       }
-                       if(e.getMessage().startsWith("too much stuff")) {
-                               throw afe("DATEDIF() not registered");
-                       }
-                       // some other unexpected error
-                       throw e;
-               }
-               assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
-       }
-       public void testDdb() {
-
-               String formula = getCellFormula(1);
-               if("externalflag(1,1,1,1,1)".equals(formula)) {
-                       throw afe("DDB() not registered");
-               }
-               assertEquals("DDB(1,1,1,1,1)", formula);
-       }
-       public void testAtan() {
-
-               String formula = getCellFormula(2);
-               if(formula.equals("ARCTAN(1)")) {
-                       throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
-               }
-               assertEquals("ATAN(1)", formula);
-       }
-
-       public void testUsdollar() {
-       
-               String formula = getCellFormula(3);
-               if(formula.equals("YEN(1)")) {
-                       throw afe("func ix 204 registered as YEN() instead of USDOLLAR()");
-               }
-               assertEquals("USDOLLAR(1)", formula);
-       }
-
-       public void testDBCS() {
-       
-               String formula;
-               try {
-                       formula = getCellFormula(4);
-               } catch (IllegalStateException e) {
-                       if(e.getMessage().startsWith("too much stuff")) {
-                               throw afe("DBCS() not registered");
-                       }
-                       // some other unexpected error
-                       throw e;
-               } catch (NegativeArraySizeException e) {
-                       throw afe("found err- DBCS() registered with -1 args");
-               }
-               if(formula.equals("JIS(\"abc\")")) {
-                       throw afe("func ix 215 registered as JIS() instead of DBCS()");
-               }
-               assertEquals("DBCS(\"abc\")", formula);
-       }
-       public void testIsnontext() {
-               
-               String formula;
-               try {
-                       formula = getCellFormula(5);
-               } catch (IllegalStateException e) {
-                       if(e.getMessage().startsWith("too much stuff")) {
-                               throw afe("ISNONTEXT() registered with wrong index");
-                       }
-                       // some other unexpected error
-                       throw e;
-               }
-               assertEquals("ISNONTEXT(\"abc\")", formula);
-       }
-       public void testDproduct() {
-               
-               String formula = getCellFormula(6);
-               assertEquals("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", formula);
-       }
-
-       private String getCellFormula(int rowIx) {
-               HSSFSheet sheet;
-               try {
-                       sheet = getSheet();
-               } catch (RecordFormatException e) {
-                       if(e.getCause() instanceof InvocationTargetException) {
-                               InvocationTargetException ite = (InvocationTargetException) e.getCause();
-                               if(ite.getTargetException() instanceof RuntimeException) {
-                                       RuntimeException re = (RuntimeException) ite.getTargetException();
-                                       if(re.getMessage().equals("Invalid built-in function index (189)")) {
-                                               throw afe("DPRODUCT() registered with wrong index");
-                                       }
-                               }
-                       }
-                       // some other unexpected error
-                       throw e;
-               }
-               String result = sheet.getRow(rowIx).getCell(0).getCellFormula();
-               if (false) {
-                       System.err.println(result);
-               }
-               return result;
-       }
-       private static AssertionFailedError afe(String msg) {
-               return new AssertionFailedError(msg);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java
deleted file mode 100644 (file)
index ef5b3ad..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
-*/
-/*
- * Created on May 29, 2005
- *
- */
-package org.apache.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *
- */
-public abstract class AbstractNumericTestCase extends TestCase {
-
-    public static final double POS_ZERO = 1E-4;
-    public static final double DIFF_TOLERANCE_FACTOR = 1E-8;
-
-    public void setUp() {
-    }
-
-    public void tearDown() {
-    }
-
-    /**
-     * Why doesnt JUnit have a method like this for doubles? 
-     * The current impl (3.8.1) of Junit has a retar*** method
-     * for comparing doubles. DO NOT use that.
-     * TODO: This class should really be in an abstract super class
-     * to avoid code duplication across this project.
-     * @param message
-     * @param baseval
-     * @param checkval
-     */
-    public static void assertEquals(String message, double baseval, double checkval, double almostZero, double diffToleranceFactor) {
-        double posZero = Math.abs(almostZero);
-        double negZero = -1 * posZero;
-        if (Double.isNaN(baseval)) {
-            assertTrue(message+": Expected " + baseval + " but was " + checkval
-                    , Double.isNaN(baseval));
-        }
-        else if (Double.isInfinite(baseval)) {
-            assertTrue(message+": Expected " + baseval + " but was " + checkval
-                    , Double.isInfinite(baseval) && ((baseval<0) == (checkval<0)));
-        }
-        else {
-            assertTrue(message+": Expected " + baseval + " but was " + checkval
-                ,baseval != 0
-                    ? Math.abs(baseval - checkval) <= Math.abs(diffToleranceFactor * baseval)
-                    : checkval < posZero && checkval > negZero);
-        }
-    }
-
-    public static void assertEquals(String msg, double baseval, double checkval) {
-        assertEquals(msg, baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
-    }
-
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java
deleted file mode 100644 (file)
index f4b2815..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-/**
- * Direct tests for all implementors of <code>Function</code>.
- *
- * @author Josh Micich
- */
-public final class AllIndividualFunctionEvaluationTests {
-
-       public static Test suite() {
-               TestSuite result = new TestSuite(AllIndividualFunctionEvaluationTests.class.getName());
-               result.addTestSuite(TestAverage.class);
-               result.addTestSuite(TestCountFuncs.class);
-               result.addTestSuite(TestDate.class);
-               result.addTestSuite(TestDays360.class);
-               result.addTestSuite(TestFinanceLib.class);
-               result.addTestSuite(TestFind.class);
-               result.addTestSuite(TestIndex.class);
-               result.addTestSuite(TestIndexFunctionFromSpreadsheet.class);
-               result.addTestSuite(TestIndirect.class);
-               result.addTestSuite(TestIsBlank.class);
-               result.addTestSuite(TestLen.class);
-               result.addTestSuite(TestLookupFunctionsFromSpreadsheet.class);
-               result.addTestSuite(TestMatch.class);
-               result.addTestSuite(TestMathX.class);
-               result.addTestSuite(TestMid.class);
-               result.addTestSuite(TestNper.class);
-               result.addTestSuite(TestOffset.class);
-               result.addTestSuite(TestPmt.class);
-               result.addTestSuite(TestRoundFuncs.class);
-               result.addTestSuite(TestRowCol.class);
-               result.addTestSuite(TestStatsLib.class);
-               result.addTestSuite(TestSubtotal.class);
-               result.addTestSuite(TestSumif.class);
-               result.addTestSuite(TestSumproduct.class);
-               result.addTestSuite(TestText.class);
-               result.addTestSuite(TestTFunc.class);
-               result.addTestSuite(TestTime.class);
-               result.addTestSuite(TestTrim.class);
-               result.addTestSuite(TestTrunc.class);
-               result.addTestSuite(TestValue.class);
-               result.addTestSuite(TestXYNumericFunction.class);
-               return result;
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java
deleted file mode 100644 (file)
index fb20919..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import org.apache.poi.hssf.record.formula.AreaI;
-import org.apache.poi.hssf.record.formula.AreaPtg;
-import org.apache.poi.hssf.record.formula.Ref3DPtg;
-import org.apache.poi.hssf.record.formula.RefPtg;
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.AreaEvalBase;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.RefEval;
-import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.TwoDEval;
-
-/**
- * Test helper class for creating mock <code>Eval</code> objects
- *
- * @author Josh Micich
- */
-public final class EvalFactory {
-
-       private EvalFactory() {
-               // no instances of this class
-       }
-
-       /**
-        * Creates a dummy AreaEval
-        * @param values empty (<code>null</code>) entries in this array will be converted to NumberEval.ZERO
-        */
-       public static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) {
-               AreaPtg areaPtg = new AreaPtg(areaRefStr);
-               return createAreaEval(areaPtg, values);
-       }
-
-       /**
-        * Creates a dummy AreaEval
-        * @param values empty (<code>null</code>) entries in this array will be converted to NumberEval.ZERO
-        */
-       public static AreaEval createAreaEval(AreaPtg areaPtg, ValueEval[] values) {
-               int nCols = areaPtg.getLastColumn() - areaPtg.getFirstColumn() + 1;
-               int nRows = areaPtg.getLastRow() - areaPtg.getFirstRow() + 1;
-               int nExpected = nRows * nCols;
-               if (values.length != nExpected) {
-                       throw new RuntimeException("Expected " + nExpected + " values but got " + values.length);
-               }
-               for (int i = 0; i < nExpected; i++) {
-                       if (values[i] == null) {
-                               values[i] = NumberEval.ZERO;
-                       }
-               }
-               return new MockAreaEval(areaPtg, values);
-       }
-
-       /**
-        * Creates a single RefEval (with value zero)
-        */
-       public static RefEval createRefEval(String refStr) {
-               return createRefEval(refStr, NumberEval.ZERO);
-       }
-       public static RefEval createRefEval(String refStr, ValueEval value) {
-               return new MockRefEval(new RefPtg(refStr), value);
-       }
-
-       private static final class MockAreaEval extends AreaEvalBase {
-               private final ValueEval[] _values;
-               public MockAreaEval(AreaI areaPtg, ValueEval[] values) {
-                       super(areaPtg);
-                       _values = values;
-               }
-               private MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn, ValueEval[] values) {
-                       super(firstRow, firstColumn, lastRow, lastColumn);
-                       _values = values;
-               }
-               public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
-                       if (relativeRowIndex < 0 || relativeRowIndex >=getHeight()) {
-                               throw new IllegalArgumentException("row index out of range");
-                       }
-                       int width = getWidth();
-                       if (relativeColumnIndex < 0 || relativeColumnIndex >=width) {
-                               throw new IllegalArgumentException("column index out of range");
-                       }
-                       int oneDimensionalIndex = relativeRowIndex * width + relativeColumnIndex;
-                       return _values[oneDimensionalIndex];
-               }
-               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
-                       if (relFirstRowIx < 0 || relFirstColIx < 0
-                                       || relLastRowIx >= getHeight() || relLastColIx >= getWidth()) {
-                               throw new RuntimeException("Operation not implemented on this mock object");
-                       }
-
-                       if (relFirstRowIx == 0 && relFirstColIx == 0
-                                       && relLastRowIx == getHeight()-1 && relLastColIx == getWidth()-1) {
-                               return this;
-                       }
-                       ValueEval[] values = transpose(_values, getWidth(), relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-                       return new MockAreaEval(getFirstRow() + relFirstRowIx, getFirstColumn() + relFirstColIx,
-                                       getFirstRow() + relLastRowIx, getFirstColumn() + relLastColIx, values);
-               }
-               private static ValueEval[] transpose(ValueEval[] srcValues, int srcWidth,
-                               int relFirstRowIx, int relLastRowIx,
-                               int relFirstColIx, int relLastColIx) {
-                       int height = relLastRowIx - relFirstRowIx + 1;
-                       int width = relLastColIx - relFirstColIx + 1;
-                       ValueEval[] result = new ValueEval[height * width];
-                       for (int r=0; r<height; r++) {
-                               int srcRowIx = r + relFirstRowIx;
-                               for (int c=0; c<width; c++) {
-                                       int srcColIx = c + relFirstColIx;
-                                       int destIx = r * width + c;
-                                       int srcIx = srcRowIx * srcWidth + srcColIx;
-                                       result[destIx] = srcValues[srcIx];
-                               }
-                       }
-                       return result;
-               }
-               public TwoDEval getRow(int rowIndex) {
-                       if (rowIndex >= getHeight()) {
-                               throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
-                                               + ".  Allowable range is (0.." + getHeight() + ").");
-                       }
-                       ValueEval[] values = new ValueEval[getWidth()];
-                       for (int i = 0; i < values.length; i++) {
-                               values[i] = getRelativeValue(rowIndex, i);
-                       }
-                       return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn(), values);
-               }
-               public TwoDEval getColumn(int columnIndex) {
-                       if (columnIndex >= getWidth()) {
-                               throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
-                                               + ".  Allowable range is (0.." + getWidth() + ").");
-                       }
-                       ValueEval[] values = new ValueEval[getHeight()];
-                       for (int i = 0; i < values.length; i++) {
-                               values[i] = getRelativeValue(i, columnIndex);
-                       }
-                       return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex, values);
-               }
-       }
-
-       private static final class MockRefEval extends RefEvalBase {
-               private final ValueEval _value;
-               public MockRefEval(RefPtg ptg, ValueEval value) {
-                       super(ptg.getRow(), ptg.getColumn());
-                       _value = value;
-               }
-               public MockRefEval(Ref3DPtg ptg, ValueEval value) {
-                       super(ptg.getRow(), ptg.getColumn());
-                       _value = value;
-               }
-               public ValueEval getInnerValueEval() {
-                       return _value;
-               }
-               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
-                       throw new RuntimeException("Operation not implemented on this mock object");
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java
deleted file mode 100644 (file)
index 1d43923..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.eval.NotImplementedException;
-
-/**
- * Test helper class for invoking functions with numeric results.
- *
- * @author Josh Micich
- */
-public final class NumericFunctionInvoker {
-
-       private NumericFunctionInvoker() {
-               // no instances of this class
-       }
-
-       private static final class NumericEvalEx extends Exception {
-               public NumericEvalEx(String msg) {
-                       super(msg);
-               }
-       }
-
-       /**
-        * Invokes the specified function with the arguments.
-        * <p/>
-        * Assumes that the cell coordinate parameters of
-        *  <code>Function.evaluate(args, srcCellRow, srcCellCol)</code>
-        * are not required.
-        * <p/>
-        * This method cannot be used for confirming error return codes.  Any non-numeric evaluation
-        * result causes the current junit test to fail.
-        */
-       public static double invoke(Function f, ValueEval[] args) {
-               return invoke(f, args, -1, -1);
-       }
-       /**
-        * Invokes the specified operator with the arguments.
-        * <p/>
-        * This method cannot be used for confirming error return codes.  Any non-numeric evaluation
-        * result causes the current junit test to fail.
-        */
-       public static double invoke(Function f, ValueEval[] args, int srcCellRow, int srcCellCol) {
-               try {
-                       return invokeInternal(f, args, srcCellRow, srcCellCol);
-               } catch (NumericEvalEx e) {
-                       throw new AssertionFailedError("Evaluation of function (" + f.getClass().getName()
-                                       + ") failed: " + e.getMessage());
-               }
-       }
-       /**
-        * Formats nicer error messages for the junit output
-        */
-       private static double invokeInternal(Function target, ValueEval[] args, int srcCellRow, int srcCellCol)
-                               throws NumericEvalEx {
-               ValueEval evalResult;
-               try {
-                       evalResult = target.evaluate(args, srcCellRow, (short)srcCellCol);
-               } catch (NotImplementedException e) {
-                       throw new NumericEvalEx("Not implemented:" + e.getMessage());
-               }
-
-               if(evalResult == null) {
-                       throw new NumericEvalEx("Result object was null");
-               }
-               if(evalResult instanceof ErrorEval) {
-                       ErrorEval ee = (ErrorEval) evalResult;
-                       throw new NumericEvalEx(formatErrorMessage(ee));
-               }
-               if(!(evalResult instanceof NumericValueEval)) {
-                       throw new NumericEvalEx("Result object type (" + evalResult.getClass().getName()
-                                       + ") is invalid.  Expected implementor of ("
-                                       + NumericValueEval.class.getName() + ")");
-               }
-
-               NumericValueEval result = (NumericValueEval) evalResult;
-               return result.getNumberValue();
-       }
-       private static String formatErrorMessage(ErrorEval ee) {
-               if(errorCodesAreEqual(ee, ErrorEval.VALUE_INVALID)) {
-                       return "Error code: #VALUE! (invalid value)";
-               }
-               return "Error code=" + ee.getErrorCode();
-       }
-       private static boolean errorCodesAreEqual(ErrorEval a, ErrorEval b) {
-               if(a==b) {
-                       return true;
-               }
-               return a.getErrorCode() == b.getErrorCode();
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestAverage.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestAverage.java
deleted file mode 100644 (file)
index 5a4d52b..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-/**
- * Tests for Excel function AVERAGE()
- *
- * @author Josh Micich
- */
-public final class TestAverage extends TestCase {
-
-       private static ValueEval invokeAverage(ValueEval[] args) {
-               return AggregateFunction.AVERAGE.evaluate(args, -1, (short)-1);
-       }
-
-       private void confirmAverage(ValueEval[] args, double expected) {
-               ValueEval result = invokeAverage(args);
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
-       }
-
-       private void confirmAverage(ValueEval[] args, ErrorEval expectedError) {
-               ValueEval result = invokeAverage(args);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
-       }
-
-       public void testBasic() {
-
-               ValueEval[] values = {
-                               new NumberEval(1),
-                               new NumberEval(2),
-                               new NumberEval(3),
-                               new NumberEval(4),
-               };
-
-               confirmAverage(values, 2.5);
-
-               values = new ValueEval[] {
-                               new NumberEval(1),
-                               new NumberEval(2),
-                               BlankEval.instance,
-                               new NumberEval(3),
-                               BlankEval.instance,
-                               new NumberEval(4),
-                               BlankEval.instance,
-               };
-
-               confirmAverage(values, 2.5);
-       }
-
-       /**
-        * Valid cases where values are not pure numbers
-        */
-       public void testUnusualArgs() {
-               ValueEval[] values = {
-                               new NumberEval(1),
-                               new NumberEval(2),
-                               BoolEval.TRUE,
-                               BoolEval.FALSE,
-               };
-
-               confirmAverage(values, 1.0);
-
-       }
-
-       public void testErrors() {
-               ValueEval[] values = {
-                               new NumberEval(1),
-                               ErrorEval.NAME_INVALID,
-                               new NumberEval(3),
-                               ErrorEval.DIV_ZERO,
-               };
-               confirmAverage(values, ErrorEval.NAME_INVALID);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java
deleted file mode 100644 (file)
index bb3cfab..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.OperandResolver;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Test cases for COUNT(), COUNTA() COUNTIF(), COUNTBLANK()
- *
- * @author Josh Micich
- */
-public final class TestCountFuncs extends TestCase {
-
-       private static final String NULL = null;
-
-       public void testCountBlank() {
-
-               AreaEval range;
-               ValueEval[] values;
-
-               values = new ValueEval[] {
-                               new NumberEval(0),
-                               new StringEval(""),     // note - does not match blank
-                               BoolEval.TRUE,
-                               BoolEval.FALSE,
-                               ErrorEval.DIV_ZERO,
-                               BlankEval.instance,
-               };
-               range = EvalFactory.createAreaEval("A1:B3", values);
-               confirmCountBlank(1, range);
-
-               values = new ValueEval[] {
-                               new NumberEval(0),
-                               new StringEval(""),     // note - does not match blank
-                               BlankEval.instance,
-                               BoolEval.FALSE,
-                               BoolEval.TRUE,
-                               BlankEval.instance,
-               };
-               range = EvalFactory.createAreaEval("A1:B3", values);
-               confirmCountBlank(2, range);
-       }
-
-       public void testCountA() {
-
-               ValueEval[] args;
-
-               args = new ValueEval[] {
-                       new NumberEval(0),
-               };
-               confirmCountA(1, args);
-
-               args = new ValueEval[] {
-                       new NumberEval(0),
-                       new NumberEval(0),
-                       new StringEval(""),
-               };
-               confirmCountA(3, args);
-
-               args = new ValueEval[] {
-                       EvalFactory.createAreaEval("D2:F5", new ValueEval[12]),
-               };
-               confirmCountA(12, args);
-
-               args = new ValueEval[] {
-                       EvalFactory.createAreaEval("D1:F5", new ValueEval[15]),
-                       EvalFactory.createRefEval("A1"),
-                       EvalFactory.createAreaEval("A1:G6", new ValueEval[42]),
-                       new NumberEval(0),
-               };
-               confirmCountA(59, args);
-       }
-
-       public void testCountIf() {
-
-               AreaEval range;
-               ValueEval[] values;
-
-               // when criteria is a boolean value
-               values = new ValueEval[] {
-                               new NumberEval(0),
-                               new StringEval("TRUE"), // note - does not match boolean TRUE
-                               BoolEval.TRUE,
-                               BoolEval.FALSE,
-                               BoolEval.TRUE,
-                               BlankEval.instance,
-               };
-               range = EvalFactory.createAreaEval("A1:B3", values);
-               confirmCountIf(2, range, BoolEval.TRUE);
-
-               // when criteria is numeric
-               values = new ValueEval[] {
-                               new NumberEval(0),
-                               new StringEval("2"),
-                               new StringEval("2.001"),
-                               new NumberEval(2),
-                               new NumberEval(2),
-                               BoolEval.TRUE,
-               };
-               range = EvalFactory.createAreaEval("A1:B3", values);
-               confirmCountIf(3, range, new NumberEval(2));
-               // note - same results when criteria is a string that parses as the number with the same value
-               confirmCountIf(3, range, new StringEval("2.00"));
-
-               // when criteria is an expression (starting with a comparison operator)
-               confirmCountIf(2, range, new StringEval(">1"));
-               // when criteria is an expression (starting with a comparison operator)
-               confirmCountIf(2, range, new StringEval(">0.5"));
-       }
-
-       public void testCriteriaPredicateNe_Bug46647() {
-               I_MatchPredicate mp = Countif.createCriteriaPredicate(new StringEval("<>aa"), 0, 0);
-               StringEval seA = new StringEval("aa"); // this should not match the criteria '<>aa'
-               StringEval seB = new StringEval("bb"); // this should match
-               if (mp.matches(seA) && !mp.matches(seB)) {
-                       throw new AssertionFailedError("Identified bug 46647");
-               }
-               assertFalse(mp.matches(seA));
-               assertTrue(mp.matches(seB));
-
-               // general tests for not-equal (<>) operator
-               AreaEval range;
-               ValueEval[] values;
-
-               values = new ValueEval[] {
-                               new StringEval("aa"),
-                               new StringEval("def"),
-                               new StringEval("aa"),
-                               new StringEval("ghi"),
-                               new StringEval("aa"),
-                               new StringEval("aa"),
-               };
-
-               range = EvalFactory.createAreaEval("A1:A6", values);
-               confirmCountIf(2, range, new StringEval("<>aa"));
-
-               values = new ValueEval[] {
-                               new StringEval("ab"),
-                               new StringEval("aabb"),
-                               new StringEval("aa"), // match
-                               new StringEval("abb"),
-                               new StringEval("aab"),
-                               new StringEval("ba"), // match
-               };
-
-               range = EvalFactory.createAreaEval("A1:A6", values);
-               confirmCountIf(2, range, new StringEval("<>a*b"));
-
-
-               values = new ValueEval[] {
-                               new NumberEval(222),
-                               new NumberEval(222),
-                               new NumberEval(111),
-                               new StringEval("aa"),
-                               new StringEval("111"),
-               };
-
-               range = EvalFactory.createAreaEval("A1:A5", values);
-               confirmCountIf(4, range, new StringEval("<>111"));
-       }
-
-       /**
-        * special case where the criteria argument is a cell reference
-        */
-       public void testCountIfWithCriteriaReference() {
-
-               ValueEval[] values = {
-                               new NumberEval(22),
-                               new NumberEval(25),
-                               new NumberEval(21),
-                               new NumberEval(25),
-                               new NumberEval(25),
-                               new NumberEval(25),
-               };
-               AreaEval arg0 = EvalFactory.createAreaEval("C1:C6", values);
-
-               ValueEval criteriaArg = EvalFactory.createRefEval("A1", new NumberEval(25));
-               ValueEval[] args=  { arg0, criteriaArg, };
-
-               double actual = NumericFunctionInvoker.invoke(new Countif(), args);
-               assertEquals(4, actual, 0D);
-       }
-
-       private static void confirmCountA(int expected, ValueEval[] args) {
-               double result = NumericFunctionInvoker.invoke(new Counta(), args);
-               assertEquals(expected, result, 0);
-       }
-       private static void confirmCountIf(int expected, AreaEval range, ValueEval criteria) {
-
-               ValueEval[] args = { range, criteria, };
-               double result = NumericFunctionInvoker.invoke(new Countif(), args);
-               assertEquals(expected, result, 0);
-       }
-       private static void confirmCountBlank(int expected, AreaEval range) {
-
-               ValueEval[] args = { range };
-               double result = NumericFunctionInvoker.invoke(new Countblank(), args);
-               assertEquals(expected, result, 0);
-       }
-
-       private static I_MatchPredicate createCriteriaPredicate(ValueEval ev) {
-               return Countif.createCriteriaPredicate(ev, 0, 0);
-       }
-
-       /**
-        * the criteria arg is mostly handled by {@link OperandResolver#getSingleValue(org.apache.poi.hssf.record.formula.eval.ValueEval, int, int)}}
-        */
-       public void testCountifAreaCriteria() {
-               int srcColIx = 2; // anything but column A
-
-               ValueEval v0 = new NumberEval(2.0);
-               ValueEval v1 = new StringEval("abc");
-               ValueEval v2 = ErrorEval.DIV_ZERO;
-
-               AreaEval ev = EvalFactory.createAreaEval("A10:A12", new ValueEval[] { v0, v1, v2, });
-
-               I_MatchPredicate mp;
-               mp = Countif.createCriteriaPredicate(ev, 9, srcColIx);
-               confirmPredicate(true, mp, srcColIx);
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
-
-               mp = Countif.createCriteriaPredicate(ev, 10, srcColIx);
-               confirmPredicate(false, mp, srcColIx);
-               confirmPredicate(true, mp, "abc");
-               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
-
-               mp = Countif.createCriteriaPredicate(ev, 11, srcColIx);
-               confirmPredicate(false, mp, srcColIx);
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(true, mp, ErrorEval.DIV_ZERO);
-               confirmPredicate(false, mp, ErrorEval.VALUE_INVALID);
-
-               // tricky: indexing outside of A10:A12
-               // even this #VALUE! error gets used by COUNTIF as valid criteria
-               mp = Countif.createCriteriaPredicate(ev, 12, srcColIx);
-               confirmPredicate(false, mp, srcColIx);
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
-               confirmPredicate(true, mp, ErrorEval.VALUE_INVALID);
-       }
-
-       public void testCountifEmptyStringCriteria() {
-               I_MatchPredicate mp;
-
-               // pred '=' matches blank cell but not empty string
-               mp = createCriteriaPredicate(new StringEval("="));
-               confirmPredicate(false, mp, "");
-               confirmPredicate(true, mp, NULL);
-
-               // pred '' matches both blank cell but not empty string
-               mp = createCriteriaPredicate(new StringEval(""));
-               confirmPredicate(true, mp, "");
-               confirmPredicate(true, mp, NULL);
-
-               // pred '<>' matches empty string but not blank cell
-               mp = createCriteriaPredicate(new StringEval("<>"));
-               confirmPredicate(false, mp, NULL);
-               confirmPredicate(true, mp, "");
-       }
-
-       public void testCountifComparisons() {
-               I_MatchPredicate mp;
-
-               mp = createCriteriaPredicate(new StringEval(">5"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(false, mp, 5);
-               confirmPredicate(true, mp, 6);
-
-               mp = createCriteriaPredicate(new StringEval("<=5"));
-               confirmPredicate(true, mp, 4);
-               confirmPredicate(true, mp, 5);
-               confirmPredicate(false, mp, 6);
-               confirmPredicate(false, mp, "4.9");
-               confirmPredicate(false, mp, "4.9t");
-               confirmPredicate(false, mp, "5.1");
-               confirmPredicate(false, mp, NULL);
-
-               mp = createCriteriaPredicate(new StringEval("=abc"));
-               confirmPredicate(true, mp, "abc");
-
-               mp = createCriteriaPredicate(new StringEval("=42"));
-               confirmPredicate(false, mp, 41);
-               confirmPredicate(true, mp, 42);
-               confirmPredicate(true, mp, "42");
-
-               mp = createCriteriaPredicate(new StringEval(">abc"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(true, mp, "abd");
-
-               mp = createCriteriaPredicate(new StringEval(">4t3"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(false, mp, 500);
-               confirmPredicate(true, mp, "500");
-               confirmPredicate(true, mp, "4t4");
-       }
-
-       /**
-        * the criteria arg value can be an error code (the error does not
-        * propagate to the COUNTIF result).
-        */
-       public void testCountifErrorCriteria() {
-               I_MatchPredicate mp;
-
-               mp = createCriteriaPredicate(new StringEval("#REF!"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(false, mp, "#REF!");
-               confirmPredicate(true, mp, ErrorEval.REF_INVALID);
-
-               mp = createCriteriaPredicate(new StringEval("<#VALUE!"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(false, mp, "#DIV/0!");
-               confirmPredicate(false, mp, "#REF!");
-               confirmPredicate(true, mp, ErrorEval.DIV_ZERO);
-               confirmPredicate(false, mp, ErrorEval.REF_INVALID);
-
-               // not quite an error literal, should be treated as plain text
-               mp = createCriteriaPredicate(new StringEval("<=#REF!a"));
-               confirmPredicate(false, mp, 4);
-               confirmPredicate(true, mp, "#DIV/0!");
-               confirmPredicate(true, mp, "#REF!");
-               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
-               confirmPredicate(false, mp, ErrorEval.REF_INVALID);
-       }
-
-       public void testWildCards() {
-               I_MatchPredicate mp;
-
-               mp = createCriteriaPredicate(new StringEval("a*b"));
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(true, mp, "ab");
-               confirmPredicate(true, mp, "axxb");
-               confirmPredicate(false, mp, "xab");
-
-               mp = createCriteriaPredicate(new StringEval("a?b"));
-               confirmPredicate(false, mp, "abc");
-               confirmPredicate(false, mp, "ab");
-               confirmPredicate(false, mp, "axxb");
-               confirmPredicate(false, mp, "xab");
-               confirmPredicate(true, mp, "axb");
-
-               mp = createCriteriaPredicate(new StringEval("a~?"));
-               confirmPredicate(false, mp, "a~a");
-               confirmPredicate(false, mp, "a~?");
-               confirmPredicate(true, mp, "a?");
-
-               mp = createCriteriaPredicate(new StringEval("~*a"));
-               confirmPredicate(false, mp, "~aa");
-               confirmPredicate(false, mp, "~*a");
-               confirmPredicate(true, mp, "*a");
-
-               mp = createCriteriaPredicate(new StringEval("12?12"));
-               confirmPredicate(false, mp, 12812);
-               confirmPredicate(true, mp, "12812");
-               confirmPredicate(false, mp, "128812");
-       }
-       public void testNotQuiteWildCards() {
-               I_MatchPredicate mp;
-
-               // make sure special reg-ex chars are treated like normal chars
-               mp = createCriteriaPredicate(new StringEval("a.b"));
-               confirmPredicate(false, mp, "aab");
-               confirmPredicate(true, mp, "a.b");
-
-
-               mp = createCriteriaPredicate(new StringEval("a~b"));
-               confirmPredicate(false, mp, "ab");
-               confirmPredicate(false, mp, "axb");
-               confirmPredicate(false, mp, "a~~b");
-               confirmPredicate(true, mp, "a~b");
-
-               mp = createCriteriaPredicate(new StringEval(">a*b"));
-               confirmPredicate(false, mp, "a(b");
-               confirmPredicate(true, mp, "aab");
-               confirmPredicate(false, mp, "a*a");
-               confirmPredicate(true, mp, "a*c");
-       }
-
-       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, int value) {
-               assertEquals(expectedResult, matchPredicate.matches(new NumberEval(value)));
-       }
-       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, String value) {
-               ValueEval ev = value == null ? BlankEval.instance : new StringEval(value);
-               assertEquals(expectedResult, matchPredicate.matches(ev));
-       }
-       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, ErrorEval value) {
-               assertEquals(expectedResult, matchPredicate.matches(value));
-       }
-
-       public void testCountifFromSpreadsheet() {
-               testCountFunctionFromSpreadsheet("countifExamples.xls", 1, 2, 3, "countif");
-       }
-
-       public void testCountBlankFromSpreadsheet() {
-               testCountFunctionFromSpreadsheet("countblankExamples.xls", 1, 3, 4, "countblank");
-       }
-
-       private static void testCountFunctionFromSpreadsheet(String FILE_NAME, int START_ROW_IX, int COL_IX_ACTUAL, int COL_IX_EXPECTED, String functionName) {
-
-               int failureCount = 0;
-               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME);
-               HSSFSheet sheet = wb.getSheetAt(0);
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               int maxRow = sheet.getLastRowNum();
-               for (int rowIx=START_ROW_IX; rowIx<maxRow; rowIx++) {
-                       HSSFRow row = sheet.getRow(rowIx);
-                       if(row == null) {
-                               continue;
-                       }
-                       HSSFCell cell = row.getCell(COL_IX_ACTUAL);
-                       CellValue cv = fe.evaluate(cell);
-                       double actualValue = cv.getNumberValue();
-                       double expectedValue = row.getCell(COL_IX_EXPECTED).getNumericCellValue();
-                       if (actualValue != expectedValue) {
-                               System.err.println("Problem with test case on row " + (rowIx+1) + " "
-                                               + "Expected = (" + expectedValue + ") Actual=(" + actualValue + ") ");
-                               failureCount++;
-                       }
-               }
-
-               if (failureCount > 0) {
-                       throw new AssertionFailedError(failureCount + " " + functionName
-                                       + " evaluations failed. See stderr for more details");
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java
deleted file mode 100644 (file)
index eac8bfd..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
- */
-public final class TestDate extends TestCase {
-
-    private HSSFCell cell11;
-    private HSSFFormulaEvaluator evaluator;
-
-    public void setUp() {
-        HSSFWorkbook wb = new HSSFWorkbook();
-        HSSFSheet sheet = wb.createSheet("new sheet");
-        cell11 = sheet.createRow(0).createCell(0);
-        cell11.setCellType(HSSFCell.CELL_TYPE_FORMULA);
-        evaluator = new HSSFFormulaEvaluator(wb);
-    }
-
-    /**
-     * Test disabled pending a fix in the formula evaluator
-     * TODO - create MissingArgEval and modify the formula evaluator to handle this
-     */
-    public void DISABLEDtestSomeArgumentsMissing() {
-        confirm("DATE(, 1, 0)", 0.0);
-        confirm("DATE(, 1, 1)", 1.0);
-    }
-
-    public void testValid() {
-
-        confirm("DATE(1900, 1, 1)", 1);
-        confirm("DATE(1900, 1, 32)", 32);
-        confirm("DATE(1900, 222, 1)", 6727);
-        confirm("DATE(1900, 2, 0)", 31);
-        confirm("DATE(2000, 1, 222)", 36747.00);
-        confirm("DATE(2007, 1, 1)", 39083);
-    }
-
-    public void testBugDate() {
-        confirm("DATE(1900, 2, 29)", 60);
-        confirm("DATE(1900, 2, 30)", 61);
-        confirm("DATE(1900, 1, 222)", 222);
-        confirm("DATE(1900, 1, 2222)", 2222);
-        confirm("DATE(1900, 1, 22222)", 22222);
-    }
-
-    public void testPartYears() {
-        confirm("DATE(4, 1, 1)", 1462.00);
-        confirm("DATE(14, 1, 1)", 5115.00);
-        confirm("DATE(104, 1, 1)", 37987.00);
-        confirm("DATE(1004, 1, 1)", 366705.00);
-    }
-
-    private void confirm(String formulaText, double expectedResult) {
-        cell11.setCellFormula(formulaText);
-        evaluator.clearAllCachedResultValues();
-        CellValue cv = evaluator.evaluate(cell11);
-        if (cv.getCellType() != Cell.CELL_TYPE_NUMERIC) {
-            throw new AssertionFailedError("Wrong result type: " + cv.formatAsString());
-        }
-        double actualValue = cv.getNumberValue();
-        assertEquals(expectedResult, actualValue, 0);
-    }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDays360.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDays360.java
deleted file mode 100644 (file)
index e517ac9..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.BoolEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.usermodel.HSSFDateUtil;
-
-/**
- * @author Josh Micich
- */
-public final class TestDays360 extends TestCase {
-
-       /**
-        * @param month 1-based
-        */
-       private static Date makeDate(int year, int month, int day) {
-
-               Calendar cal = new GregorianCalendar(year, month-1, day, 0, 0, 0);
-               cal.set(Calendar.MILLISECOND, 0);
-               return cal.getTime();
-       }
-       private static Date decrementDay(Date d) {
-               Calendar c = new GregorianCalendar();
-               c.setTimeInMillis(d.getTime());
-               c.add(Calendar.DAY_OF_MONTH, -1);
-               return c.getTime();
-       }
-       private static String fmt(Date d) {
-               Calendar c = new GregorianCalendar();
-               c.setTimeInMillis(d.getTime());
-               StringBuilder sb = new StringBuilder();
-               sb.append(c.get(Calendar.YEAR));
-               sb.append("/");
-               sb.append(c.get(Calendar.MONTH)+1);
-               sb.append("/");
-               sb.append(c.get(Calendar.DAY_OF_MONTH));
-               return sb.toString();
-       }
-
-
-       public void testBasic() {
-               confirm(120, 2009, 1, 15, 2009, 5, 15);
-               confirm(158, 2009, 1, 26, 2009, 7, 4);
-
-               // same results in leap years
-               confirm(120, 2008, 1, 15, 2008, 5, 15);
-               confirm(158, 2008, 1, 26, 2008, 7, 4);
-
-               // longer time spans
-               confirm(562, 2008, 8, 11, 2010, 3, 3);
-               confirm(916, 2007, 2, 23, 2009, 9, 9);
-       }
-
-       private static void confirm(int expResult, int y1, int m1, int d1, int y2, int m2, int d2) {
-               confirm(expResult, makeDate(y1, m1, d1), makeDate(y2, m2, d2), false);
-               confirm(-expResult, makeDate(y2, m2, d2), makeDate(y1, m1, d1), false);
-
-       }
-       /**
-        * The <tt>method</tt> parameter only makes a difference when the second parameter
-        * is the last day of the month that does <em>not</em> have 30 days.
-        */
-       public void DISABLED_testMonthBoundaries() {
-               // jan
-               confirmMonthBoundary(false, 1, 0, 0, 2, 3, 4);
-               confirmMonthBoundary(true,  1, 0, 0, 1, 3, 4);
-               // feb
-               confirmMonthBoundary(false, 2,-2, 1, 2, 3, 4);
-               confirmMonthBoundary(true,  2, 0, 1, 2, 3, 4);
-               // mar
-               confirmMonthBoundary(false, 3, 0, 0, 2, 3, 4);
-               confirmMonthBoundary(true,  3, 0, 0, 1, 3, 4);
-               // apr
-               confirmMonthBoundary(false, 4, 0, 1, 2, 3, 4);
-               confirmMonthBoundary(true,  4, 0, 1, 2, 3, 4);
-               // may
-               confirmMonthBoundary(false, 5, 0, 0, 2, 3, 4);
-               confirmMonthBoundary(true,  5, 0, 0, 1, 3, 4);
-               // jun
-               confirmMonthBoundary(false, 6, 0, 1, 2, 3, 4);
-               confirmMonthBoundary(true,  6, 0, 1, 2, 3, 4);
-               // etc...
-       }
-
-
-       /**
-        * @param monthNo 1-based
-        * @param diffs
-        */
-       private static void confirmMonthBoundary(boolean method, int monthNo, int...diffs) {
-               Date firstDayOfNextMonth = makeDate(2001, monthNo+1, 1);
-               Date secondArg = decrementDay(firstDayOfNextMonth);
-               Date firstArg = secondArg;
-
-               for (int i = 0; i < diffs.length; i++) {
-                       int expResult = diffs[i];
-                       confirm(expResult, firstArg, secondArg, method);
-                       firstArg = decrementDay(firstArg);
-               }
-
-       }
-       private static void confirm(int expResult, Date firstArg, Date secondArg, boolean method) {
-
-               ValueEval ve;
-               if (method) {
-                       // TODO enable 3rd arg -
-                       ve = invokeDays360(convert(firstArg), convert(secondArg), BoolEval.valueOf(method));
-               } else {
-                       ve = invokeDays360(convert(firstArg), convert(secondArg));
-               }
-               if (ve instanceof NumberEval) {
-
-                       NumberEval numberEval = (NumberEval) ve;
-                       if (numberEval.getNumberValue() != expResult) {
-                               throw new AssertionFailedError(fmt(firstArg) + " " + fmt(secondArg) + " " + method +
-                                               " wrong result got (" + numberEval.getNumberValue()
-                                               + ") but expected (" + expResult + ")");
-                       }
-                       //      System.err.println(fmt(firstArg) + " " + fmt(secondArg) + " " + method + " success got (" + expResult + ")");
-                       return;
-               }
-               throw new AssertionFailedError("wrong return type (" + ve.getClass().getName() + ")");
-       }
-       private static ValueEval invokeDays360(ValueEval...args) {
-               return new Days360().evaluate(args, -1, -1);
-       }
-       private static NumberEval convert(Date d) {
-               return new NumberEval(HSSFDateUtil.getExcelDate(d));
-       }
-}
-
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java
deleted file mode 100644 (file)
index 4dfe1fb..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
-*/
-/*
- * Created on May 23, 2005
- *
- */
-package org.apache.poi.hssf.record.formula.functions;
-
-
-/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *
- */
-public class TestFinanceLib extends AbstractNumericTestCase {
-
-    public void testFv() {
-        double f, r, y, p, x;
-        int n;
-        boolean t = false;
-        
-        r = 0; n = 3; y = 2; p = 7; t = true;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = -13;
-        assertEquals("fv ", x, f);
-        
-        r = 1; n = 10; y = 100; p = 10000; t = false;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = -10342300;
-        assertEquals("fv ", x, f);
-        
-        r = 1; n = 10; y = 100; p = 10000; t = true;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = -10444600;
-        assertEquals("fv ", x, f);
-        
-        r = 2; n = 12; y = 120; p = 12000; t = false;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = -6409178400d;
-        assertEquals("fv ", x, f);
-        
-        r = 2; n = 12; y = 120; p = 12000; t = true;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = -6472951200d;
-        assertEquals("fv ", x, f);
-        
-        // cross tests with pv
-        r = 2.95; n = 13; y = 13000; p = -4406.78544294496; t = false;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = 333891.230010986; // as returned by excel
-        assertEquals("fv ", x, f);
-        
-        r = 2.95; n = 13; y = 13000; p = -17406.7852148156; t = true;
-        f = FinanceLib.fv(r, n, y, p, t);
-        x = 333891.230102539; // as returned by excel
-        assertEquals("fv ", x, f);
-        
-    }
-    public void testNpv() {
-        double r, v[], npv, x;
-        
-        r = 1; v = new double[]{100, 200, 300, 400};
-        npv = FinanceLib.npv(r, v);
-        x = 162.5;
-        assertEquals("npv ", x, npv);
-        
-        r = 2.5; v = new double[]{1000, 666.66666, 333.33, 12.2768416};
-        npv = FinanceLib.npv(r, v);
-        x = 347.99232604144827;
-        assertEquals("npv ", x, npv);
-        
-        r = 12.33333; v = new double[]{1000, 0, -900, -7777.5765};
-        npv = FinanceLib.npv(r, v);
-        x = 74.3742433377061;
-        assertEquals("npv ", x, npv);
-        
-        r = 0.05; v = new double[]{200000, 300000.55, 400000, 1000000, 6000000, 7000000, -300000};
-        npv = FinanceLib.npv(r, v);
-        x = 11342283.4233124;
-        assertEquals("npv ", x, npv);
-    }
-    public void testPmt() {
-        double f, r, y, p, x;
-        int n;
-        boolean t = false;
-
-        r = 0; n = 3; p = 2; f = 7; t = true;
-        y = FinanceLib.pmt(r, n, p, f, t);
-        x = -3;
-        assertEquals("pmt ", x, y);    
-        
-        // cross check with pv
-        r = 1; n = 10; p = -109.66796875; f = 10000; t = false;
-        y = FinanceLib.pmt(r, n, p, f, t);
-        x = 100;
-        assertEquals("pmt ", x, y);    
-        
-        r = 1; n = 10; p = -209.5703125; f = 10000; t = true;
-        y = FinanceLib.pmt(r, n, p, f, t);
-        x = 100;
-        assertEquals("pmt ", x, y);
-        
-        // cross check with fv
-        r = 2; n = 12; f = -6409178400d; p = 12000; t = false;
-        y = FinanceLib.pmt(r, n, p, f, t);
-        x = 120;
-        assertEquals("pmt ", x, y);    
-        
-        r = 2; n = 12; f = -6472951200d; p = 12000; t = true;
-        y = FinanceLib.pmt(r, n, p, f, t);
-        x = 120;
-        assertEquals("pmt ", x, y);
-    }
-    
-    public void testPv() {
-        double f, r, y, p, x;
-        int n;
-        boolean t = false;
-
-        r = 0; n = 3; y = 2; f = 7; t = true;
-        f = FinanceLib.pv(r, n, y, f, t);
-        x = -13;
-        assertEquals("pv ", x, f);
-
-        r = 1; n = 10; y = 100; f = 10000; t = false;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = -109.66796875;
-        assertEquals("pv ", x, p);    
-        
-        r = 1; n = 10; y = 100; f = 10000; t = true;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = -209.5703125;
-        assertEquals("pv ", x, p);    
-        
-        r = 2.95; n = 13; y = 13000; f = 333891.23; t = false;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = -4406.78544294496;
-        assertEquals("pv ", x, p);
-        
-        r = 2.95; n = 13; y = 13000; f = 333891.23; t = true;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = -17406.7852148156;
-        assertEquals("pv ", x, p);
-        
-        // cross tests with fv
-        r = 2; n = 12; y = 120; f = -6409178400d; t = false;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = 12000;
-        assertEquals("pv ", x, p);
-        
-        r = 2; n = 12; y = 120; f = -6472951200d; t = true;
-        p = FinanceLib.pv(r, n, y, f, t);
-        x = 12000; 
-        assertEquals("pv ", x, p);
-        
-    }
-    
-    public void testNper() {
-        double f, r, y, p, x, n;
-        boolean t = false;
-        
-        r = 0; y = 7; p = 2; f = 3; t = false;
-        n = FinanceLib.nper(r, y, p, f, t);
-        x = -0.71428571429; // can you believe it? excel returns nper as a fraction!??
-        assertEquals("nper ", x, n);    
-        
-        // cross check with pv
-        r = 1; y = 100; p = -109.66796875; f = 10000; t = false;
-        n = FinanceLib.nper(r, y, p, f, t);
-        x = 10;
-        assertEquals("nper ", x, n);    
-        
-        r = 1; y = 100; p = -209.5703125; f = 10000; t = true;
-        n = FinanceLib.nper(r, y, p, f, t);
-        x = 10;
-        assertEquals("nper ", x, n);
-        
-        // cross check with fv
-        r = 2; y = 120; f = -6409178400d; p = 12000; t = false;
-        n = FinanceLib.nper(r, y, p, f, t);
-        x = 12;
-        assertEquals("nper ", x, n);    
-        
-        r = 2; y = 120; f = -6472951200d; p = 12000; t = true;
-        n = FinanceLib.nper(r, y, p, f, t);
-        x = 12; 
-        assertEquals("nper ", x, n);
-    }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestFind.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestFind.java
deleted file mode 100644 (file)
index 8fb3b2b..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Tests for {@link Financed}
- * 
- * @author Torstein Svendsen (torstei@officenet.no)
- */
-public final class TestFind extends TestCase {
-
-       public void testFind() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFCell cell = wb.createSheet().createRow(0).createCell(0);
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-
-               confirmResult(fe, cell, "find(\"h\", \"haystack\")", 1);
-               confirmResult(fe, cell, "find(\"a\", \"haystack\",2)", 2);
-               confirmResult(fe, cell, "find(\"a\", \"haystack\",3)", 6);
-
-               // number args converted to text
-               confirmResult(fe, cell, "find(7, 32768)", 3);
-               confirmResult(fe, cell, "find(\"34\", 1341235233412, 3)", 10);
-               confirmResult(fe, cell, "find(5, 87654)", 4);
-
-               // Errors
-               confirmError(fe, cell, "find(\"n\", \"haystack\")", HSSFErrorConstants.ERROR_VALUE);
-               confirmError(fe, cell, "find(\"k\", \"haystack\",9)", HSSFErrorConstants.ERROR_VALUE);
-               confirmError(fe, cell, "find(\"k\", \"haystack\",#REF!)", HSSFErrorConstants.ERROR_REF);
-               confirmError(fe, cell, "find(\"k\", \"haystack\",0)", HSSFErrorConstants.ERROR_VALUE);
-               confirmError(fe, cell, "find(#DIV/0!, #N/A, #REF!)", HSSFErrorConstants.ERROR_DIV_0);
-               confirmError(fe, cell, "find(2, #N/A, #REF!)", HSSFErrorConstants.ERROR_NA);
-       }
-
-       private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
-                       int expectedResult) {
-               cell.setCellFormula(formulaText);
-               fe.notifyUpdateCell(cell);
-               CellValue result = fe.evaluate(cell);
-               assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_NUMERIC);
-               assertEquals(expectedResult, result.getNumberValue(), 0.0);
-       }
-
-       private static void confirmError(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
-                       int expectedErrorCode) {
-               cell.setCellFormula(formulaText);
-               fe.notifyUpdateCell(cell);
-               CellValue result = fe.evaluate(cell);
-               assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_ERROR);
-               assertEquals(expectedErrorCode, result.getErrorValue());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java
deleted file mode 100644 (file)
index a6ae6ef..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.util.Arrays;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.MissingArgEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.WorkbookEvaluator;
-import org.apache.poi.ss.util.CellRangeAddress;
-
-/**
- * Tests for the INDEX() function.</p>
- *
- * This class contains just a few specific cases that directly invoke {@link Index},
- * with minimum overhead.<br/>
- * Another test: {@link TestIndexFunctionFromSpreadsheet} operates from a higher level
- * and has far greater coverage of input permutations.<br/>
- *
- * @author Josh Micich
- */
-public final class TestIndex extends TestCase {
-
-       private static final Index FUNC_INST = new Index();
-       private static final double[] TEST_VALUES0 = {
-                       1, 2,
-                       3, 4,
-                       5, 6,
-                       7, 8,
-                       9, 10,
-                       11, 12,
-       };
-
-       /**
-        * For the case when the first argument to INDEX() is an area reference
-        */
-       public void testEvaluateAreaReference() {
-
-               double[] values = TEST_VALUES0;
-               confirmAreaEval("C1:D6", values, 4, 1, 7);
-               confirmAreaEval("C1:D6", values, 6, 2, 12);
-               confirmAreaEval("C1:D6", values, 3, 1, 5);
-
-               // now treat same data as 3 columns, 4 rows
-               confirmAreaEval("C10:E13", values, 2, 2, 5);
-               confirmAreaEval("C10:E13", values, 4, 1, 10);
-       }
-
-       /**
-        * @param areaRefString in Excel notation e.g. 'D2:E97'
-        * @param dValues array of evaluated values for the area reference
-        * @param rowNum 1-based
-        * @param colNum 1-based, pass -1 to signify argument not present
-        */
-       private static void confirmAreaEval(String areaRefString, double[] dValues,
-                       int rowNum, int colNum, double expectedResult) {
-               ValueEval[] values = new ValueEval[dValues.length];
-               for (int i = 0; i < values.length; i++) {
-                       values[i] = new NumberEval(dValues[i]);
-               }
-               AreaEval arg0 = EvalFactory.createAreaEval(areaRefString, values);
-
-               ValueEval[] args;
-               if (colNum > 0) {
-                       args = new ValueEval[] { arg0, new NumberEval(rowNum), new NumberEval(colNum), };
-               } else {
-                       args = new ValueEval[] { arg0, new NumberEval(rowNum), };
-               }
-
-               double actual = invokeAndDereference(args);
-               assertEquals(expectedResult, actual, 0D);
-       }
-
-       private static double invokeAndDereference(ValueEval[] args) {
-               ValueEval ve = FUNC_INST.evaluate(args, -1, -1);
-               ve = WorkbookEvaluator.dereferenceResult(ve, -1, -1);
-               assertEquals(NumberEval.class, ve.getClass());
-               return ((NumberEval)ve).getNumberValue();
-       }
-
-       /**
-        * Tests expressions like "INDEX(A1:C1,,2)".<br/>
-        * This problem was found while fixing bug 47048 and is observable up to svn r773441.
-        */
-       public void testMissingArg() {
-               ValueEval[] values = {
-                               new NumberEval(25.0),
-                               new NumberEval(26.0),
-                               new NumberEval(28.0),
-               };
-               AreaEval arg0 = EvalFactory.createAreaEval("A10:C10", values);
-               ValueEval[] args = new ValueEval[] { arg0, MissingArgEval.instance, new NumberEval(2), };
-               ValueEval actualResult;
-               try {
-                       actualResult = FUNC_INST.evaluate(args, -1, -1);
-               } catch (RuntimeException e) {
-                       if (e.getMessage().equals("Unexpected arg eval type (org.apache.poi.hssf.record.formula.eval.MissingArgEval")) {
-                               throw new AssertionFailedError("Identified bug 47048b - INDEX() should support missing-arg");
-                       }
-                       throw e;
-               }
-               // result should be an area eval "B10:B10"
-               AreaEval ae = confirmAreaEval("B10:B10", actualResult);
-               actualResult = ae.getValue(0, 0);
-               assertEquals(NumberEval.class, actualResult.getClass());
-               assertEquals(26.0, ((NumberEval)actualResult).getNumberValue(), 0.0);
-       }
-
-       /**
-        * When the argument to INDEX is a reference, the result should be a reference
-        * A formula like "OFFSET(INDEX(A1:B2,2,1),1,1,1,1)" should return the value of cell B3.
-        * This works because the INDEX() function returns a reference to A2 (not the value of A2)
-        */
-       public void testReferenceResult() {
-               ValueEval[] values = new ValueEval[4];
-               Arrays.fill(values, NumberEval.ZERO);
-               AreaEval arg0 = EvalFactory.createAreaEval("A1:B2", values);
-               ValueEval[] args = new ValueEval[] { arg0, new NumberEval(2), new NumberEval(1), };
-               ValueEval ve = FUNC_INST.evaluate(args, -1, -1);
-               confirmAreaEval("A2:A2", ve);
-       }
-
-       /**
-        * Confirms that the result is an area ref with the specified coordinates
-        * @return <tt>ve</tt> cast to {@link AreaEval} if it is valid
-        */
-       private static AreaEval confirmAreaEval(String refText, ValueEval ve) {
-               CellRangeAddress cra = CellRangeAddress.valueOf(refText);
-               assertTrue(ve instanceof AreaEval);
-               AreaEval ae = (AreaEval) ve;
-               assertEquals(cra.getFirstRow(), ae.getFirstRow());
-               assertEquals(cra.getFirstColumn(), ae.getFirstColumn());
-               assertEquals(cra.getLastRow(), ae.getLastRow());
-               assertEquals(cra.getLastColumn(), ae.getLastColumn());
-               return ae;
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java
deleted file mode 100644 (file)
index ffd841f..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.io.PrintStream;
-
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Tests INDEX() as loaded from a test data spreadsheet.<p/>
- *
- * @author Josh Micich
- */
-public final class TestIndexFunctionFromSpreadsheet extends TestCase {
-
-       private static final class Result {
-               public static final int SOME_EVALUATIONS_FAILED = -1;
-               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
-               public static final int NO_EVALUATIONS_FOUND = 0;
-       }
-
-       /**
-        * This class defines constants for navigating around the test data spreadsheet used for these tests.
-        */
-       private static final class SS {
-
-               /** Name of the test spreadsheet (found in the standard test data folder) */
-               public final static String FILENAME = "IndexFunctionTestCaseData.xls";
-
-               public static final int COLUMN_INDEX_EVALUATION = 2; // Column 'C'
-               public static final int COLUMN_INDEX_EXPECTED_RESULT = 3; // Column 'D'
-
-       }
-
-       // Note - multiple failures are aggregated before ending.
-       // If one or more functions fail, a single AssertionFailedError is thrown at the end
-       private int _evaluationFailureCount;
-       private int _evaluationSuccessCount;
-
-
-
-       private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
-               if (expected == null) {
-                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
-               }
-               if(actual == null) {
-                       throw new AssertionFailedError(msg + " - actual value was null");
-               }
-               if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
-                       confirmErrorResult(msg, expected.getErrorCellValue(), actual);
-                       return;
-               }
-               if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
-                       throw unexpectedError(msg, expected, actual.getErrorValue());
-               }
-               if(actual.getCellType() != expected.getCellType()) {
-                       throw wrongTypeError(msg, expected, actual);
-               }
-
-
-               switch (expected.getCellType()) {
-                       case HSSFCell.CELL_TYPE_BOOLEAN:
-                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
-                               break;
-                       case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
-                               throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
-                       case HSSFCell.CELL_TYPE_NUMERIC:
-                               assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
-                               break;
-                       case HSSFCell.CELL_TYPE_STRING:
-                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
-                               break;
-               }
-       }
-
-
-       private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
-               return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
-                               + actualValue.formatAsString()
-                               + " but the expected result was "
-                               + formatValue(expectedCell)
-                               );
-       }
-       private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
-               return new AssertionFailedError(msgPrefix + " Error code ("
-                               + ErrorEval.getText(actualErrorCode)
-                               + ") was evaluated, but the expected result was "
-                               + formatValue(expected)
-                               );
-       }
-
-
-       private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
-               if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
-                       throw new AssertionFailedError(msgPrefix + " Expected cell error ("
-                                       + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
-                                       + actual.formatAsString());
-               }
-               if(expectedErrorCode != actual.getErrorValue()) {
-                       throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
-                                       + ErrorEval.getText(expectedErrorCode)
-                                       + ") but actual error code was ("
-                                       + ErrorEval.getText(actual.getErrorValue())
-                                       + ")");
-               }
-       }
-
-
-       private static String formatValue(HSSFCell expecedCell) {
-               switch (expecedCell.getCellType()) {
-                       case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
-                       case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
-                       case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
-                       case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
-               }
-               throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
-       }
-
-
-       protected void setUp() {
-               _evaluationFailureCount = 0;
-               _evaluationSuccessCount = 0;
-       }
-
-       public void testFunctionsFromTestSpreadsheet() {
-               HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-
-               processTestSheet(workbook, workbook.getSheetName(0));
-
-               // confirm results
-               String successMsg = "There were "
-                               + _evaluationSuccessCount + " function(s) without error";
-               if(_evaluationFailureCount > 0) {
-                       String msg = _evaluationFailureCount + " evaluation(s) failed.  " + successMsg;
-                       throw new AssertionFailedError(msg);
-               }
-               if(false) { // normally no output for successful tests
-                       System.out.println(getClass().getName() + ": " + successMsg);
-               }
-       }
-
-       private void processTestSheet(HSSFWorkbook workbook, String sheetName) {
-               HSSFSheet sheet = workbook.getSheetAt(0);
-               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
-               int maxRows = sheet.getLastRowNum()+1;
-               int result = Result.NO_EVALUATIONS_FOUND; // so far
-
-               for(int rowIndex=0; rowIndex<maxRows; rowIndex++) {
-                       HSSFRow r = sheet.getRow(rowIndex);
-                       if(r == null) {
-                               continue;
-                       }
-                       HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
-                       if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
-                               continue;
-                       }
-                       HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
-
-                       String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c);
-                       try {
-                               CellValue actualValue = evaluator.evaluate(c);
-                               confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
-                               _evaluationSuccessCount ++;
-                               if(result != Result.SOME_EVALUATIONS_FAILED) {
-                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
-                               }
-                       } catch (RuntimeException e) {
-                               _evaluationFailureCount ++;
-                               printShortStackTrace(System.err, e, msgPrefix);
-                               result = Result.SOME_EVALUATIONS_FAILED;
-                       } catch (AssertionFailedError e) {
-                               _evaluationFailureCount ++;
-                               printShortStackTrace(System.err, e, msgPrefix);
-                               result = Result.SOME_EVALUATIONS_FAILED;
-                       }
-               }
-       }
-
-
-       private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c) {
-
-               StringBuffer sb = new StringBuffer();
-               CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
-               sb.append(cr.formatAsString());
-               sb.append(" [formula: ").append(c.getCellFormula()).append(" ]");
-               return sb.toString();
-       }
-
-       /**
-        * Useful to keep output concise when expecting many failures to be reported by this test case
-        */
-       private static void printShortStackTrace(PrintStream ps, Throwable e, String msgPrefix) {
-               System.err.println("Problem with " + msgPrefix);
-               StackTraceElement[] stes = e.getStackTrace();
-
-               int startIx = 0;
-               // skip any top frames inside junit.framework.Assert
-               while(startIx<stes.length) {
-                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
-                               break;
-                       }
-                       startIx++;
-               }
-               // skip bottom frames (part of junit framework)
-               int endIx = startIx+1;
-               while(endIx < stes.length) {
-                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
-                               break;
-                       }
-                       endIx++;
-               }
-               if(startIx >= endIx) {
-                       // something went wrong. just print the whole stack trace
-                       e.printStackTrace(ps);
-               }
-               endIx -= 4; // skip 4 frames of reflection invocation
-               ps.println(e.toString());
-               for(int i=startIx; i<endIx; i++) {
-                       ps.println("\tat " + stes[i].toString());
-               }
-       }
-}
-
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java
deleted file mode 100644 (file)
index 6be7b03..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.util.CellReference;
-
-/**
- * Tests for the INDIRECT() function.</p>
- *
- * @author Josh Micich
- */
-public final class TestIndirect extends TestCase {
-       // convenient access to namespace
-       private static final ErrorEval EE = null;
-
-       private static void createDataRow(HSSFSheet sheet, int rowIndex, double... vals) {
-               HSSFRow row = sheet.createRow(rowIndex);
-               for (int i = 0; i < vals.length; i++) {
-                       row.createCell(i).setCellValue(vals[i]);
-               }
-       }
-
-       private static HSSFWorkbook createWBA() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet1 = wb.createSheet("Sheet1");
-               HSSFSheet sheet2 = wb.createSheet("Sheet2");
-               HSSFSheet sheet3 = wb.createSheet("John's sales");
-
-               createDataRow(sheet1, 0, 11, 12, 13, 14);
-               createDataRow(sheet1, 1, 21, 22, 23, 24);
-               createDataRow(sheet1, 2, 31, 32, 33, 34);
-
-               createDataRow(sheet2, 0, 50, 55, 60, 65);
-               createDataRow(sheet2, 1, 51, 56, 61, 66);
-               createDataRow(sheet2, 2, 52, 57, 62, 67);
-
-               createDataRow(sheet3, 0, 30, 31, 32);
-               createDataRow(sheet3, 1, 33, 34, 35);
-
-        HSSFName name1 = wb.createName();
-        name1.setNameName("sales1");
-        name1.setRefersToFormula("Sheet1!A1:D1");
-
-        HSSFName name2 = wb.createName();
-        name2.setNameName("sales2");
-        name2.setRefersToFormula("Sheet2!B1:C3");
-
-        HSSFRow row = sheet1.createRow(3);
-        row.createCell(0).setCellValue("sales1");  //A4
-        row.createCell(1).setCellValue("sales2");  //B4
-
-               return wb;
-       }
-
-       private static HSSFWorkbook createWBB() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet1 = wb.createSheet("Sheet1");
-               HSSFSheet sheet2 = wb.createSheet("Sheet2");
-               HSSFSheet sheet3 = wb.createSheet("## Look here!");
-
-               createDataRow(sheet1, 0, 400, 440, 480, 520);
-               createDataRow(sheet1, 1, 420, 460, 500, 540);
-
-               createDataRow(sheet2, 0, 50, 55, 60, 65);
-               createDataRow(sheet2, 1, 51, 56, 61, 66);
-
-               createDataRow(sheet3, 0, 42);
-
-               return wb;
-       }
-
-       public void testBasic() {
-
-               HSSFWorkbook wbA = createWBA();
-               HSSFCell c = wbA.getSheetAt(0).createRow(5).createCell(2);
-               HSSFFormulaEvaluator feA = new HSSFFormulaEvaluator(wbA);
-
-               // non-error cases
-               confirm(feA, c, "INDIRECT(\"C2\")", 23);
-               confirm(feA, c, "INDIRECT(\"$C2\")", 23);
-               confirm(feA, c, "INDIRECT(\"C$2\")", 23);
-               confirm(feA, c, "SUM(INDIRECT(\"Sheet2!B1:C3\"))", 351); // area ref
-               confirm(feA, c, "SUM(INDIRECT(\"Sheet2! B1 : C3 \"))", 351); // spaces in area ref
-               confirm(feA, c, "SUM(INDIRECT(\"'John''s sales'!A1:C1\"))", 93); // special chars in sheet name
-               confirm(feA, c, "INDIRECT(\"'Sheet1'!B3\")", 32); // redundant sheet name quotes
-               confirm(feA, c, "INDIRECT(\"sHeet1!B3\")", 32); // case-insensitive sheet name
-               confirm(feA, c, "INDIRECT(\" D3 \")", 34); // spaces around cell ref
-               confirm(feA, c, "INDIRECT(\"Sheet1! D3 \")", 34); // spaces around cell ref
-               confirm(feA, c, "INDIRECT(\"A1\", TRUE)", 11); // explicit arg1. only TRUE supported so far
-
-               confirm(feA, c, "INDIRECT(\"A1:G1\")", 13); // de-reference area ref (note formula is in C4)
-
-        confirm(feA, c, "SUM(INDIRECT(A4))", 50); // indirect defined name
-        confirm(feA, c, "SUM(INDIRECT(B4))", 351); // indirect defined name pointinh to other sheet
-
-               // simple error propagation:
-
-               // arg0 is evaluated to text first
-               confirm(feA, c, "INDIRECT(#DIV/0!)", EE.DIV_ZERO);
-               confirm(feA, c, "INDIRECT(#DIV/0!)", EE.DIV_ZERO);
-               confirm(feA, c, "INDIRECT(#NAME?, \"x\")", EE.NAME_INVALID);
-               confirm(feA, c, "INDIRECT(#NUM!, #N/A)", EE.NUM_ERROR);
-
-               // arg1 is evaluated to boolean before arg0 is decoded
-               confirm(feA, c, "INDIRECT(\"garbage\", #N/A)", EE.NA);
-               confirm(feA, c, "INDIRECT(\"garbage\", \"\")", EE.VALUE_INVALID); // empty string is not valid boolean
-               confirm(feA, c, "INDIRECT(\"garbage\", \"flase\")", EE.VALUE_INVALID); // must be "TRUE" or "FALSE"
-
-
-               // spaces around sheet name (with or without quotes makes no difference)
-               confirm(feA, c, "INDIRECT(\"'Sheet1 '!D3\")", EE.REF_INVALID);
-               confirm(feA, c, "INDIRECT(\" Sheet1!D3\")", EE.REF_INVALID);
-               confirm(feA, c, "INDIRECT(\"'Sheet1' !D3\")", EE.REF_INVALID);
-
-
-               confirm(feA, c, "SUM(INDIRECT(\"'John's sales'!A1:C1\"))", EE.REF_INVALID); // bad quote escaping
-               confirm(feA, c, "INDIRECT(\"[Book1]Sheet1!A1\")", EE.REF_INVALID); // unknown external workbook
-               confirm(feA, c, "INDIRECT(\"Sheet3!A1\")", EE.REF_INVALID); // unknown sheet
-               if (false) { // TODO - support evaluation of defined names
-                       confirm(feA, c, "INDIRECT(\"Sheet1!IW1\")", EE.REF_INVALID); // bad column
-                       confirm(feA, c, "INDIRECT(\"Sheet1!A65537\")", EE.REF_INVALID); // bad row
-               }
-               confirm(feA, c, "INDIRECT(\"Sheet1!A 1\")", EE.REF_INVALID); // space in cell ref
-       }
-
-       public void testMultipleWorkbooks() {
-               HSSFWorkbook wbA = createWBA();
-               HSSFCell cellA = wbA.getSheetAt(0).createRow(10).createCell(0);
-               HSSFFormulaEvaluator feA = new HSSFFormulaEvaluator(wbA);
-
-               HSSFWorkbook wbB = createWBB();
-               HSSFCell cellB = wbB.getSheetAt(0).createRow(10).createCell(0);
-               HSSFFormulaEvaluator feB = new HSSFFormulaEvaluator(wbB);
-
-               String[] workbookNames = { "MyBook", "Figures for January", };
-               HSSFFormulaEvaluator[] evaluators = { feA, feB, };
-               HSSFFormulaEvaluator.setupEnvironment(workbookNames, evaluators);
-
-               confirm(feB, cellB, "INDIRECT(\"'[Figures for January]## Look here!'!A1\")", 42); // same wb
-               confirm(feA, cellA, "INDIRECT(\"'[Figures for January]## Look here!'!A1\")", 42); // across workbooks
-
-               // 2 level recursion
-               confirm(feB, cellB, "INDIRECT(\"[MyBook]Sheet2!A1\")", 50); // set up (and check) first level
-               confirm(feA, cellA, "INDIRECT(\"'[Figures for January]Sheet1'!A11\")", 50); // points to cellB
-       }
-
-       private static void confirm(FormulaEvaluator fe, Cell cell, String formula,
-                       double expectedResult) {
-               fe.clearAllCachedResultValues();
-               cell.setCellFormula(formula);
-               CellValue cv = fe.evaluate(cell);
-               if (cv.getCellType() != Cell.CELL_TYPE_NUMERIC) {
-                       throw new AssertionFailedError("expected numeric cell type but got " + cv.formatAsString());
-               }
-               assertEquals(expectedResult, cv.getNumberValue(), 0.0);
-       }
-       private static void confirm(FormulaEvaluator fe, Cell cell, String formula,
-                       ErrorEval expectedResult) {
-               fe.clearAllCachedResultValues();
-               cell.setCellFormula(formula);
-               CellValue cv = fe.evaluate(cell);
-               if (cv.getCellType() != Cell.CELL_TYPE_ERROR) {
-                       throw new AssertionFailedError("expected error cell type but got " + cv.formatAsString());
-               }
-               int expCode = expectedResult.getErrorCode();
-               if (cv.getErrorValue() != expCode) {
-                       throw new AssertionFailedError("Expected error '" + EE.getText(expCode)
-                                       + "' but got '" + cv.formatAsString() + "'.");
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIsBlank.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIsBlank.java
deleted file mode 100644 (file)
index 5168cd9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.CellValue;
-/**
- * Tests for Excel function ISBLANK()
- * 
- * @author Josh Micich
- */
-public final class TestIsBlank extends TestCase {
-
-       public void test3DArea() {
-        HSSFWorkbook wb = new HSSFWorkbook();
-        HSSFSheet sheet1 = wb.createSheet();
-        wb.setSheetName(0, "Sheet1");
-        wb.createSheet();
-        wb.setSheetName(1, "Sheet2");
-        HSSFRow row = sheet1.createRow(0);
-        HSSFCell cell = row.createCell(0);
-
-         
-        cell.setCellFormula("isblank(Sheet2!A1:A1)");
-        
-        HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-        CellValue result = fe.evaluate(cell);
-        assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, result.getCellType());
-        assertEquals(true, result.getBooleanValue());
-        
-        cell.setCellFormula("isblank(D7:D7)");
-        
-        result = fe.evaluate(cell);
-        assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, result.getCellType());
-        assertEquals(true, result.getBooleanValue());
-   }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLeftRight.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLeftRight.java
deleted file mode 100644 (file)
index 055e493..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-import junit.framework.TestCase;
-
-/**
- * 
- * Test cases for {@link TextFunction#LEFT} and {@link TextFunction#RIGHT}
- * 
- * @author Brendan Nolan
- *
- */
-public class TestLeftRight extends TestCase {
-
-       private static final NumberEval NEGATIVE_OPERAND = new NumberEval(-1.0);
-       private static final StringEval ANY_STRING_VALUE = new StringEval("ANYSTRINGVALUE");
-
-       
-       private static ValueEval invokeLeft(ValueEval text, ValueEval operand) {
-               ValueEval[] args = new ValueEval[] { text, operand };
-               return TextFunction.LEFT.evaluate(args, -1, (short)-1);
-       }
-       
-       private static ValueEval invokeRight(ValueEval text, ValueEval operand) {
-               ValueEval[] args = new ValueEval[] { text, operand };
-               return TextFunction.RIGHT.evaluate(args, -1, (short)-1);
-       }
-       
-       public void testLeftRight_bug49841() {
-
-               try {
-                       invokeLeft(ANY_STRING_VALUE, NEGATIVE_OPERAND);
-                       invokeRight(ANY_STRING_VALUE, NEGATIVE_OPERAND);
-               } catch (StringIndexOutOfBoundsException e) {
-                       fail("Identified bug 49841");
-               }
-
-       }
-       
-       public void testLeftRightNegativeOperand() {
-               
-               assertEquals(ErrorEval.VALUE_INVALID, invokeRight(ANY_STRING_VALUE, NEGATIVE_OPERAND));         
-               assertEquals(ErrorEval.VALUE_INVALID, invokeLeft(ANY_STRING_VALUE, NEGATIVE_OPERAND));
-
-       }
-       
-       
-       
-       
-
-       
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLen.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLen.java
deleted file mode 100644 (file)
index be9c55a..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-/**
- * Tests for Excel function LEN()
- *
- * @author Josh Micich
- */
-public final class TestLen extends TestCase {
-
-       private static ValueEval invokeLen(ValueEval text) {
-               ValueEval[] args = new ValueEval[] { text, };
-               return TextFunction.LEN.evaluate(args, -1, (short)-1);
-       }
-
-       private void confirmLen(ValueEval text, int expected) {
-               ValueEval result = invokeLen(text);
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
-       }
-
-       private void confirmLen(ValueEval text, ErrorEval expectedError) {
-               ValueEval result = invokeLen(text);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
-       }
-
-       public void testBasic() {
-
-               confirmLen(new StringEval("galactic"), 8);
-       }
-
-       /**
-        * Valid cases where text arg is not exactly a string
-        */
-       public void testUnusualArgs() {
-
-               // text (first) arg type is number, other args are strings with fractional digits
-               confirmLen(new NumberEval(123456), 6);
-               confirmLen(BoolEval.FALSE, 5);
-               confirmLen(BoolEval.TRUE, 4);
-               confirmLen(BlankEval.instance, 0);
-       }
-
-       public void testErrors() {
-               confirmLen(ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java
deleted file mode 100644 (file)
index b0b6ece..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.io.PrintStream;
-
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.ss.usermodel.CellValue;
-
-/**
- * Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.<p/>
- * These tests have been separated from the common function and operator tests because the lookup
- * functions have more complex test cases and test data setup.
- *
- * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class
- * (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor, where execution can be observed
- *  more easily.
- *
- * @author Josh Micich
- */
-public final class TestLookupFunctionsFromSpreadsheet extends TestCase {
-
-       private static final class Result {
-               public static final int SOME_EVALUATIONS_FAILED = -1;
-               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
-               public static final int NO_EVALUATIONS_FOUND = 0;
-       }
-
-       /**
-        * This class defines constants for navigating around the test data spreadsheet used for these tests.
-        */
-       private static final class SS {
-
-               /** Name of the test spreadsheet (found in the standard test data folder) */
-               public final static String FILENAME = "LookupFunctionsTestCaseData.xls";
-
-               /** Name of the first sheet in the spreadsheet (contains comments) */
-               public final static String README_SHEET_NAME = "Read Me";
-
-
-               /** Row (zero-based) in each sheet where the evaluation cases start.   */
-               public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5'
-               /**  Index of the column that contains the function names */
-               public static final int COLUMN_INDEX_MARKER = 0; // Column 'A'
-               public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B'
-               public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C'
-               public static final int COLUMN_ROW_COMMENT = 3; // Column 'D'
-
-               /** Used to indicate when there are no more test cases on the current sheet   */
-               public static final String TEST_CASES_END_MARKER = "<end>";
-               /** Used to indicate that the test on the current row should be ignored */
-               public static final String SKIP_CURRENT_TEST_CASE_MARKER = "<skip>";
-
-       }
-
-       // Note - multiple failures are aggregated before ending.
-       // If one or more functions fail, a single AssertionFailedError is thrown at the end
-       private int _sheetFailureCount;
-       private int _sheetSuccessCount;
-       private int _evaluationFailureCount;
-       private int _evaluationSuccessCount;
-
-
-
-       private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
-               if (expected == null) {
-                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
-               }
-               if(actual == null) {
-                       throw new AssertionFailedError(msg + " - actual value was null");
-               }
-               if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
-                       confirmErrorResult(msg, expected.getErrorCellValue(), actual);
-                       return;
-               }
-               if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
-                       throw unexpectedError(msg, expected, actual.getErrorValue());
-               }
-               if(actual.getCellType() != expected.getCellType()) {
-                       throw wrongTypeError(msg, expected, actual);
-               }
-
-
-               switch (expected.getCellType()) {
-                       case HSSFCell.CELL_TYPE_BOOLEAN:
-                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
-                               break;
-                       case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
-                               throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg);
-                       case HSSFCell.CELL_TYPE_NUMERIC:
-                               assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
-                               break;
-                       case HSSFCell.CELL_TYPE_STRING:
-                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
-                               break;
-               }
-       }
-
-
-       private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
-               return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
-                               + actualValue.formatAsString()
-                               + " but the expected result was "
-                               + formatValue(expectedCell)
-                               );
-       }
-       private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
-               return new AssertionFailedError(msgPrefix + " Error code ("
-                               + ErrorEval.getText(actualErrorCode)
-                               + ") was evaluated, but the expected result was "
-                               + formatValue(expected)
-                               );
-       }
-
-
-       private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
-               if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
-                       throw new AssertionFailedError(msgPrefix + " Expected cell error ("
-                                       + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
-                                       + actual.formatAsString());
-               }
-               if(expectedErrorCode != actual.getErrorValue()) {
-                       throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
-                                       + ErrorEval.getText(expectedErrorCode)
-                                       + ") but actual error code was ("
-                                       + ErrorEval.getText(actual.getErrorValue())
-                                       + ")");
-               }
-       }
-
-
-       private static String formatValue(HSSFCell expecedCell) {
-               switch (expecedCell.getCellType()) {
-                       case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
-                       case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
-                       case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
-                       case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
-               }
-               throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
-       }
-
-
-       protected void setUp() {
-               _sheetFailureCount = 0;
-               _sheetSuccessCount = 0;
-               _evaluationFailureCount = 0;
-               _evaluationSuccessCount = 0;
-       }
-
-       public void testFunctionsFromTestSpreadsheet() {
-               HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-
-               confirmReadMeSheet(workbook);
-               int nSheets = workbook.getNumberOfSheets();
-               for(int i=1; i< nSheets; i++) {
-                       int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i));
-                       switch(sheetResult) {
-                               case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break;
-                               case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break;
-                       }
-               }
-
-               // confirm results
-               String successMsg = "There were "
-                               + _sheetSuccessCount + " successful sheets(s) and "
-                               + _evaluationSuccessCount + " function(s) without error";
-               if(_sheetFailureCount > 0) {
-                       String msg = _sheetFailureCount + " sheets(s) failed with "
-                       + _evaluationFailureCount + " evaluation(s).  " + successMsg;
-                       throw new AssertionFailedError(msg);
-               }
-               if(false) { // normally no output for successful tests
-                       System.out.println(getClass().getName() + ": " + successMsg);
-               }
-       }
-
-       private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {
-               HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
-               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
-               int maxRows = sheet.getLastRowNum()+1;
-               int result = Result.NO_EVALUATIONS_FOUND; // so far
-
-               String currentGroupComment = null;
-               for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndex<maxRows; rowIndex++) {
-                       HSSFRow r = sheet.getRow(rowIndex);
-                       String newMarkerValue = getMarkerColumnValue(r);
-                       if(r == null) {
-                               continue;
-                       }
-                       if(SS.TEST_CASES_END_MARKER.equalsIgnoreCase(newMarkerValue)) {
-                               // normal exit point
-                               return result;
-                       }
-                       if(SS.SKIP_CURRENT_TEST_CASE_MARKER.equalsIgnoreCase(newMarkerValue)) {
-                               // currently disabled test case row
-                               continue;
-                       }
-                       if(newMarkerValue != null) {
-                               currentGroupComment = newMarkerValue;
-                       }
-                       HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
-                       if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
-                               continue;
-                       }
-                       CellValue actualValue = evaluator.evaluate(c);
-                       HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
-                       String rowComment = getRowCommentColumnValue(r);
-
-                       String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c, currentGroupComment, rowComment);
-                       try {
-                               confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
-                               _evaluationSuccessCount ++;
-                               if(result != Result.SOME_EVALUATIONS_FAILED) {
-                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
-                               }
-                       } catch (RuntimeException e) {
-                               _evaluationFailureCount ++;
-                               printShortStackTrace(System.err, e);
-                               result = Result.SOME_EVALUATIONS_FAILED;
-                       } catch (AssertionFailedError e) {
-                               _evaluationFailureCount ++;
-                               printShortStackTrace(System.err, e);
-                               result = Result.SOME_EVALUATIONS_FAILED;
-                       }
-
-               }
-               throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER
-                               + "' on sheet '" + sheetName + "'");
-
-       }
-
-
-       private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c, String currentGroupComment,
-                       String rowComment) {
-
-               StringBuffer sb = new StringBuffer();
-               CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
-               sb.append(cr.formatAsString());
-               sb.append(" {=").append(c.getCellFormula()).append("}");
-
-               if(currentGroupComment != null) {
-                       sb.append(" '");
-                       sb.append(currentGroupComment);
-                       if(rowComment != null) {
-                               sb.append(" - ");
-                               sb.append(rowComment);
-                       }
-                       sb.append("' ");
-               } else {
-                       if(rowComment != null) {
-                               sb.append(" '");
-                               sb.append(rowComment);
-                               sb.append("' ");
-                       }
-               }
-
-               return sb.toString();
-       }
-
-       /**
-        * Asserts that the 'read me' comment page exists, and has this class' name in one of the
-        * cells.  This back-link is to make it easy to find this class if a reader encounters the
-        * spreadsheet first.
-        */
-       private void confirmReadMeSheet(HSSFWorkbook workbook) {
-               String firstSheetName = workbook.getSheetName(0);
-               if(!firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)) {
-                       throw new RuntimeException("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'");
-               }
-               HSSFSheet sheet = workbook.getSheetAt(0);
-               String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString();
-               assertEquals("Test class name in spreadsheet comment", getClass().getName(), specifiedClassName);
-       }
-
-
-       /**
-        * Useful to keep output concise when expecting many failures to be reported by this test case
-        */
-       private static void printShortStackTrace(PrintStream ps, Throwable e) {
-               StackTraceElement[] stes = e.getStackTrace();
-
-               int startIx = 0;
-               // skip any top frames inside junit.framework.Assert
-               while(startIx<stes.length) {
-                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
-                               break;
-                       }
-                       startIx++;
-               }
-               // skip bottom frames (part of junit framework)
-               int endIx = startIx+1;
-               while(endIx < stes.length) {
-                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
-                               break;
-                       }
-                       endIx++;
-               }
-               if(startIx >= endIx) {
-                       // something went wrong. just print the whole stack trace
-                       e.printStackTrace(ps);
-               }
-               endIx -= 4; // skip 4 frames of reflection invocation
-               ps.println(e.toString());
-               for(int i=startIx; i<endIx; i++) {
-                       ps.println("\tat " + stes[i].toString());
-               }
-
-       }
-
-       private static String getRowCommentColumnValue(HSSFRow r) {
-               return getCellTextValue(r, SS.COLUMN_ROW_COMMENT, "row comment");
-       }
-
-       private static String getMarkerColumnValue(HSSFRow r) {
-               return getCellTextValue(r, SS.COLUMN_INDEX_MARKER, "marker");
-       }
-
-       /**
-        * @return <code>null</code> if cell is missing, empty or blank
-        */
-       private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) {
-               if(r == null) {
-                       return null;
-               }
-               HSSFCell cell = r.getCell(colIndex);
-               if(cell == null) {
-                       return null;
-               }
-               if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
-                       return null;
-               }
-               if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
-                       return cell.getRichStringCellValue().getString();
-               }
-
-               throw new RuntimeException("Bad cell type for '" + columnName + "' column: ("
-                               + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java
deleted file mode 100644 (file)
index a92dd1f..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Test cases for MATCH()
- *
- * @author Josh Micich
- */
-public final class TestMatch extends TestCase {
-       /** less than or equal to */
-       private static final NumberEval MATCH_LARGEST_LTE = new NumberEval(1);
-       private static final NumberEval MATCH_EXACT = new NumberEval(0);
-       /** greater than or equal to */
-       private static final NumberEval MATCH_SMALLEST_GTE = new NumberEval(-1);
-
-
-       private static ValueEval invokeMatch(ValueEval lookup_value, ValueEval lookup_array, ValueEval match_type) {
-               ValueEval[] args = { lookup_value, lookup_array, match_type, };
-               return new Match().evaluate(args, -1, (short)-1);
-       }
-       private static void confirmInt(int expected, ValueEval actualEval) {
-               if(!(actualEval instanceof NumericValueEval)) {
-                       fail("Expected numeric result");
-               }
-               NumericValueEval nve = (NumericValueEval)actualEval;
-               assertEquals(expected, nve.getNumberValue(), 0);
-       }
-
-       public void testSimpleNumber() {
-
-               ValueEval[] values = {
-                       new NumberEval(4),
-                       new NumberEval(5),
-                       new NumberEval(10),
-                       new NumberEval(10),
-                       new NumberEval(25),
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
-
-               confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE));
-               confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
-               confirmInt(4, invokeMatch(new NumberEval(10), ae, MATCH_LARGEST_LTE));
-               confirmInt(3, invokeMatch(new NumberEval(10), ae, MATCH_EXACT));
-               confirmInt(4, invokeMatch(new NumberEval(20), ae, MATCH_LARGEST_LTE));
-               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT));
-       }
-
-       public void testReversedNumber() {
-
-               ValueEval[] values = {
-                       new NumberEval(25),
-                       new NumberEval(10),
-                       new NumberEval(10),
-                       new NumberEval(10),
-                       new NumberEval(4),
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
-
-               confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_SMALLEST_GTE));
-               confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_EXACT));
-               confirmInt(4, invokeMatch(new NumberEval(9), ae, MATCH_SMALLEST_GTE));
-               confirmInt(1, invokeMatch(new NumberEval(20), ae, MATCH_SMALLEST_GTE));
-               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT));
-               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(26), ae, MATCH_SMALLEST_GTE));
-       }
-
-       public void testSimpleString() {
-
-               ValueEval[] values = {
-                       new StringEval("Albert"),
-                       new StringEval("Charles"),
-                       new StringEval("Ed"),
-                       new StringEval("Greg"),
-                       new StringEval("Ian"),
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
-
-               // Note String comparisons are case insensitive
-               confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_LARGEST_LTE));
-               confirmInt(3, invokeMatch(new StringEval("eD"), ae, MATCH_LARGEST_LTE));
-               confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_EXACT));
-               confirmInt(3, invokeMatch(new StringEval("ed"), ae, MATCH_EXACT));
-               confirmInt(4, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
-               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
-       }
-
-       public void testSimpleBoolean() {
-
-               ValueEval[] values = {
-                               BoolEval.FALSE,
-                               BoolEval.FALSE,
-                               BoolEval.TRUE,
-                               BoolEval.TRUE,
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A4", values);
-
-               // Note String comparisons are case insensitive
-               confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE));
-               confirmInt(1, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT));
-               confirmInt(4, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE));
-               confirmInt(3, invokeMatch(BoolEval.TRUE, ae, MATCH_EXACT));
-       }
-
-       public void testHeterogeneous() {
-
-               ValueEval[] values = {
-                               new NumberEval(4),
-                               BoolEval.FALSE,
-                               new NumberEval(5),
-                               new StringEval("Albert"),
-                               BoolEval.FALSE,
-                               BoolEval.TRUE,
-                               new NumberEval(10),
-                               new StringEval("Charles"),
-                               new StringEval("Ed"),
-                               new NumberEval(10),
-                               new NumberEval(25),
-                               BoolEval.TRUE,
-                               new StringEval("Ed"),
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A13", values);
-
-               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Aaron"), ae, MATCH_LARGEST_LTE));
-
-               confirmInt(5, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE));
-               confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT));
-               confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE));
-               confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
-
-               confirmInt(8, invokeMatch(new StringEval("CHARLES"), ae, MATCH_EXACT));
-
-               confirmInt(4, invokeMatch(new StringEval("Ben"), ae, MATCH_LARGEST_LTE));
-
-               confirmInt(13, invokeMatch(new StringEval("ED"), ae, MATCH_LARGEST_LTE));
-               confirmInt(9, invokeMatch(new StringEval("ED"), ae, MATCH_EXACT));
-
-               confirmInt(13, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
-               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
-
-               confirmInt(11, invokeMatch(new NumberEval(30), ae, MATCH_LARGEST_LTE));
-               confirmInt(12, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE));
-       }
-
-
-       /**
-        * Ensures that the match_type argument can be an <tt>AreaEval</tt>.<br/>
-        * Bugzilla 44421
-        */
-       public void testMatchArgTypeArea() {
-
-               ValueEval[] values = {
-                       new NumberEval(4),
-                       new NumberEval(5),
-                       new NumberEval(10),
-                       new NumberEval(10),
-                       new NumberEval(25),
-               };
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
-
-               AreaEval matchAE = EvalFactory.createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, });
-
-               try {
-                       confirmInt(4, invokeMatch(new NumberEval(10), ae, matchAE));
-               } catch (RuntimeException e) {
-                       if(e.getMessage().startsWith("Unexpected match_type type")) {
-                               // identified bug 44421
-                               fail(e.getMessage());
-                       }
-                       // some other error ??
-                       throw e;
-               }
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java
deleted file mode 100644 (file)
index a88f011..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
-*/
-/*
- * Created on May 23, 2005
- *
- */
-package org.apache.poi.hssf.record.formula.functions;
-
-import org.apache.poi.hssf.record.formula.functions.XYNumericFunction.Accumulator;
-
-
-/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *  
- */
-public class TestMathX extends AbstractNumericTestCase {
-
-    public void testAcosh() {
-        double d = 0;
-
-        d = MathX.acosh(0);
-        assertTrue("Acosh 0 is NaN", Double.isNaN(d));
-
-        d = MathX.acosh(1);
-        assertEquals("Acosh 1 ", 0, d);
-
-        d = MathX.acosh(-1);
-        assertTrue("Acosh -1 is NaN", Double.isNaN(d));
-
-        d = MathX.acosh(100);
-        assertEquals("Acosh 100 ", 5.298292366d, d);
-
-        d = MathX.acosh(101.001);
-        assertEquals("Acosh 101.001 ", 5.308253091d, d);
-
-        d = MathX.acosh(200000);
-        assertEquals("Acosh 200000 ", 12.89921983d, d);
-
-    }
-
-    public void testAsinh() {
-        double d = 0;
-
-        d = MathX.asinh(0);
-        assertEquals("asinh 0", d, 0);
-
-        d = MathX.asinh(1);
-        assertEquals("asinh 1 ", 0.881373587, d);
-
-        d = MathX.asinh(-1);
-        assertEquals("asinh -1 ", -0.881373587, d);
-
-        d = MathX.asinh(-100);
-        assertEquals("asinh -100 ", -5.298342366, d);
-
-        d = MathX.asinh(100);
-        assertEquals("asinh 100 ", 5.298342366, d);
-
-        d = MathX.asinh(200000);
-        assertEquals("asinh 200000", 12.899219826096400, d);
-
-        d = MathX.asinh(-200000);
-        assertEquals("asinh -200000 ", -12.899223853137, d);
-
-    }
-
-    public void testAtanh() {
-        double d = 0;
-        d = MathX.atanh(0);
-        assertEquals("atanh 0", d, 0);
-
-        d = MathX.atanh(1);
-        assertEquals("atanh 1 ", Double.POSITIVE_INFINITY, d);
-
-        d = MathX.atanh(-1);
-        assertEquals("atanh -1 ", Double.NEGATIVE_INFINITY, d);
-
-        d = MathX.atanh(-100);
-        assertEquals("atanh -100 ", Double.NaN, d);
-
-        d = MathX.atanh(100);
-        assertEquals("atanh 100 ", Double.NaN, d);
-
-        d = MathX.atanh(200000);
-        assertEquals("atanh 200000", Double.NaN, d);
-
-        d = MathX.atanh(-200000);
-        assertEquals("atanh -200000 ", Double.NaN, d);
-
-        d = MathX.atanh(0.1);
-        assertEquals("atanh 0.1", 0.100335348, d);
-
-        d = MathX.atanh(-0.1);
-        assertEquals("atanh -0.1 ", -0.100335348, d);
-
-    }
-
-    public void testCosh() {
-        double d = 0;
-        d = MathX.cosh(0);
-        assertEquals("cosh 0", 1, d);
-
-        d = MathX.cosh(1);
-        assertEquals("cosh 1 ", 1.543080635, d);
-
-        d = MathX.cosh(-1);
-        assertEquals("cosh -1 ", 1.543080635, d);
-
-        d = MathX.cosh(-100);
-        assertEquals("cosh -100 ", 1.344058570908070E+43, d);
-
-        d = MathX.cosh(100);
-        assertEquals("cosh 100 ", 1.344058570908070E+43, d);
-
-        d = MathX.cosh(15);
-        assertEquals("cosh 15", 1634508.686, d);
-
-        d = MathX.cosh(-15);
-        assertEquals("cosh -15 ", 1634508.686, d);
-
-        d = MathX.cosh(0.1);
-        assertEquals("cosh 0.1", 1.005004168, d);
-
-        d = MathX.cosh(-0.1);
-        assertEquals("cosh -0.1 ", 1.005004168, d);
-
-    }
-
-    public void testTanh() {
-        double d = 0;
-        d = MathX.tanh(0);
-        assertEquals("tanh 0", 0, d);
-
-        d = MathX.tanh(1);
-        assertEquals("tanh 1 ", 0.761594156, d);
-
-        d = MathX.tanh(-1);
-        assertEquals("tanh -1 ", -0.761594156, d);
-
-        d = MathX.tanh(-100);
-        assertEquals("tanh -100 ", -1, d);
-
-        d = MathX.tanh(100);
-        assertEquals("tanh 100 ", 1, d);
-
-        d = MathX.tanh(15);
-        assertEquals("tanh 15", 1, d);
-
-        d = MathX.tanh(-15);
-        assertEquals("tanh -15 ", -1, d);
-
-        d = MathX.tanh(0.1);
-        assertEquals("tanh 0.1", 0.099667995, d);
-
-        d = MathX.tanh(-0.1);
-        assertEquals("tanh -0.1 ", -0.099667995, d);
-
-    }
-
-    public void testMax() {
-        double[] d = new double[100];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        double m = MathX.max(d);
-        assertEquals("Max ", 20.1, m);
-        
-        d = new double[1000];
-        m = MathX.max(d);
-        assertEquals("Max ", 0, m);
-        
-        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
-        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
-        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
-        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
-        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
-        m = MathX.max(d);
-        assertEquals("Max ", 20.1, m);
-        
-        d = new double[20];
-        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
-        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
-        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
-        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
-        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
-        m = MathX.max(d);
-        assertEquals("Max ", -1.1, m);
-        
-    }
-
-    public void testMin() {
-        double[] d = new double[100];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        double m = MathX.min(d);
-        assertEquals("Min ", 0, m);
-        
-        d = new double[20];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        m = MathX.min(d);
-        assertEquals("Min ", 1.1, m);
-        
-        d = new double[1000];
-        m = MathX.min(d);
-        assertEquals("Min ", 0, m);
-        
-        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
-        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
-        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
-        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
-        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
-        m = MathX.min(d);
-        assertEquals("Min ", -19.1, m);
-        
-        d = new double[20];
-        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
-        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
-        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
-        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
-        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
-        m = MathX.min(d);
-        assertEquals("Min ", -20.1, m);
-    }
-
-    public void testProduct() {
-        double[] d = new double[100];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        double m = MathX.min(d);
-        assertEquals("Min ", 0, m);
-        
-        d = new double[20];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        m = MathX.min(d);
-        assertEquals("Min ", 1.1, m);
-        
-        d = new double[1000];
-        m = MathX.min(d);
-        assertEquals("Min ", 0, m);
-        
-        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
-        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
-        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
-        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
-        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
-        m = MathX.min(d);
-        assertEquals("Min ", -19.1, m);
-        
-        d = new double[20];
-        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
-        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
-        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
-        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
-        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
-        m = MathX.min(d);
-        assertEquals("Min ", -20.1, m);
-    }
-
-    public void testMod() {
-
-        //example from Excel help
-        assertEquals(1.0, MathX.mod(3, 2));
-        assertEquals(1.0, MathX.mod(-3, 2));
-        assertEquals(-1.0, MathX.mod(3, -2));
-        assertEquals(-1.0, MathX.mod(-3, -2));
-
-        assertEquals((double) 1.4, MathX.mod(3.4, 2));
-        assertEquals((double) -1.4, MathX.mod(-3.4, -2));
-        assertEquals((double) 0.6000000000000001, MathX.mod(-3.4, 2.0));// should actually be 0.6
-        assertEquals((double) -0.6000000000000001, MathX.mod(3.4, -2.0));// should actually be -0.6
-
-        // Bugzilla 50033
-        assertEquals(1.0, MathX.mod(13, 12));
-    }
-
-    public void testNChooseK() {
-        int n=100;
-        int k=50;
-        double d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 1.00891344545564E29, d);
-        
-        n = -1; k = 1;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", Double.NaN, d);
-        
-        n = 1; k = -1;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", Double.NaN, d);
-        
-        n = 0; k = 1;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", Double.NaN, d);
-        
-        n = 1; k = 0;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 1, d);
-        
-        n = 10; k = 9;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 10, d);
-        
-        n = 10; k = 10;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 1, d);
-        
-        n = 10; k = 1;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 10, d);
-        
-        n = 1000; k = 1;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 1000, d); // awesome ;)
-        
-        n = 1000; k = 2;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 499500, d); // awesome ;)
-        
-        n = 13; k = 7;
-        d = MathX.nChooseK(n, k);
-        assertEquals("NChooseK ", 1716, d);
-        
-    }
-
-    public void testSign() {
-        final short minus = -1;
-        final short zero = 0;
-        final short plus = 1;
-        double d = 0;
-        
-        
-        assertEquals("Sign ", minus, MathX.sign(minus));
-        assertEquals("Sign ", plus, MathX.sign(plus));
-        assertEquals("Sign ", zero, MathX.sign(zero));
-        
-        d = 0;
-        assertEquals("Sign ", zero, MathX.sign(d));
-        
-        d = -1.000001;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = -.000001;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = -1E-200;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = Double.NEGATIVE_INFINITY;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = -200.11;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = -2000000000000.11;
-        assertEquals("Sign ", minus, MathX.sign(d));
-        
-        d = 1.000001;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-        d = .000001;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-        d = 1E-200;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-        d = Double.POSITIVE_INFINITY;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-        d = 200.11;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-        d = 2000000000000.11;
-        assertEquals("Sign ", plus, MathX.sign(d));
-        
-    }
-
-    public void testSinh() {
-        double d = 0;
-        d = MathX.sinh(0);
-        assertEquals("sinh 0", 0, d);
-
-        d = MathX.sinh(1);
-        assertEquals("sinh 1 ", 1.175201194, d);
-
-        d = MathX.sinh(-1);
-        assertEquals("sinh -1 ", -1.175201194, d);
-
-        d = MathX.sinh(-100);
-        assertEquals("sinh -100 ", -1.344058570908070E+43, d);
-
-        d = MathX.sinh(100);
-        assertEquals("sinh 100 ", 1.344058570908070E+43, d);
-
-        d = MathX.sinh(15);
-        assertEquals("sinh 15", 1634508.686, d);
-
-        d = MathX.sinh(-15);
-        assertEquals("sinh -15 ", -1634508.686, d);
-
-        d = MathX.sinh(0.1);
-        assertEquals("sinh 0.1", 0.10016675, d);
-
-        d = MathX.sinh(-0.1);
-        assertEquals("sinh -0.1 ", -0.10016675, d);
-
-    }
-
-    public void testSum() {
-        double[] d = new double[100];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        double s = MathX.sum(d);
-        assertEquals("Sum ", 212, s);
-        
-        d = new double[1000];
-        s = MathX.sum(d);
-        assertEquals("Sum ", 0, s);
-        
-        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
-        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
-        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
-        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
-        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
-        s = MathX.sum(d);
-        assertEquals("Sum ", 10, s);
-        
-        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
-        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
-        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
-        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
-        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
-        s = MathX.sum(d);
-        assertEquals("Sum ", -212, s);
-        
-    }
-
-    public void testSumsq() {
-        double[] d = new double[100];
-        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
-        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
-        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
-        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
-        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
-        
-        double s = MathX.sumsq(d);
-        assertEquals("Sumsq ", 2912.2, s);
-        
-        d = new double[1000];
-        s = MathX.sumsq(d);
-        assertEquals("Sumsq ", 0, s);
-        
-        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
-        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
-        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
-        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
-        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
-        s = MathX.sumsq(d);
-        assertEquals("Sumsq ", 2912.2, s);
-        
-        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
-        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
-        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
-        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
-        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
-        s = MathX.sumsq(d);
-        assertEquals("Sumsq ", 2912.2, s);
-    }
-
-    public void testFactorial() {
-        int n = 0;
-        double s = 0;
-        
-        n = 0;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", 1, s);
-        
-        n = 1;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", 1, s);
-        
-        n = 10;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", 3628800, s);
-        
-        n = 99;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", 9.33262154439E+155, s);
-        
-        n = -1;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", Double.NaN, s);
-        
-        n = Integer.MAX_VALUE;
-        s = MathX.factorial(n);
-        assertEquals("Factorial ", Double.POSITIVE_INFINITY, s);
-    }
-
-    public void testSumx2my2() {
-        double[] xarr = null;
-        double[] yarr = null;
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumx2my2(xarr, yarr, 100);
-        
-        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumx2my2(xarr, yarr, 100);
-        
-        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumx2my2(xarr, yarr, -100);
-        
-        xarr = new double[]{10};
-        yarr = new double[]{9};
-        confirmSumx2my2(xarr, yarr, 19);
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumx2my2(xarr, yarr, 0);
-    }
-
-    public void testSumx2py2() {
-        double[] xarr = null;
-        double[] yarr = null;
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumx2py2(xarr, yarr, 670);
-        
-        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumx2py2(xarr, yarr, 670);
-        
-        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumx2py2(xarr, yarr, 670);
-        
-        xarr = new double[]{10};
-        yarr = new double[]{9};
-        confirmSumx2py2(xarr, yarr, 181);
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumx2py2(xarr, yarr, 770);
-    }
-
-    public void testSumxmy2() {
-        double[] xarr = null;
-        double[] yarr = null;
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumxmy2(xarr, yarr, 10);
-        
-        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
-        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        confirmSumxmy2(xarr, yarr, 1330);
-        
-        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumxmy2(xarr, yarr, 10);
-        
-        xarr = new double[]{10};
-        yarr = new double[]{9};
-        confirmSumxmy2(xarr, yarr, 1);
-        
-        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-        confirmSumxmy2(xarr, yarr, 0);
-    }
-
-    private static void confirmSumx2my2(double[] xarr, double[] yarr, double expectedResult) {
-        confirmXY(new Sumx2my2().createAccumulator(), xarr, yarr, expectedResult);
-    }
-    private static void confirmSumx2py2(double[] xarr, double[] yarr, double expectedResult) {
-        confirmXY(new Sumx2py2().createAccumulator(), xarr, yarr, expectedResult);
-    }
-    private static void confirmSumxmy2(double[] xarr, double[] yarr, double expectedResult) {
-        confirmXY(new Sumxmy2().createAccumulator(), xarr, yarr, expectedResult);
-    }
-
-    private static void confirmXY(Accumulator acc, double[] xarr, double[] yarr,
-            double expectedResult) {
-        double result = 0.0;
-        for (int i = 0; i < xarr.length; i++) {
-            result += acc.accumulate(xarr[i], yarr[i]);
-        }
-        assertEquals(expectedResult, result, 0.0);
-    }
-    
-    public void testRound() {
-        double d = 0;
-        int p = 0;
-        
-        d = 0; p = 0;
-        assertEquals("round ", 0, MathX.round(d, p));
-        
-        d = 10; p = 0;
-        assertEquals("round ", 10, MathX.round(d, p));
-        
-        d = 123.23; p = 0;
-        assertEquals("round ", 123, MathX.round(d, p));
-        
-        d = -123.23; p = 0;
-        assertEquals("round ", -123, MathX.round(d, p));
-        
-        d = 123.12; p = 2;
-        assertEquals("round ", 123.12, MathX.round(d, p));
-        
-        d = 88.123459; p = 5;
-        assertEquals("round ", 88.12346, MathX.round(d, p));
-        
-        d = 0; p = 2;
-        assertEquals("round ", 0, MathX.round(d, p));
-        
-        d = 0; p = -1;
-        assertEquals("round ", 0, MathX.round(d, p));
-        
-        d = 0.01; p = -1;
-        assertEquals("round ", 0, MathX.round(d, p));
-
-        d = 123.12; p = -2;
-        assertEquals("round ", 100, MathX.round(d, p));
-        
-        d = 88.123459; p = -3;
-        assertEquals("round ", 0, MathX.round(d, p));
-        
-        d = 49.00000001; p = -1;
-        assertEquals("round ", 50, MathX.round(d, p));
-        
-        d = 149.999999; p = -2;
-        assertEquals("round ", 100, MathX.round(d, p));
-        
-        d = 150.0; p = -2;
-        assertEquals("round ", 200, MathX.round(d, p));
-    }
-
-    public void testRoundDown() {
-        double d = 0;
-        int p = 0;
-        
-        d = 0; p = 0;
-        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
-        
-        d = 10; p = 0;
-        assertEquals("roundDown ", 10, MathX.roundDown(d, p));
-        
-        d = 123.99; p = 0;
-        assertEquals("roundDown ", 123, MathX.roundDown(d, p));
-        
-        d = -123.99; p = 0;
-        assertEquals("roundDown ", -123, MathX.roundDown(d, p));
-        
-        d = 123.99; p = 2;
-        assertEquals("roundDown ", 123.99, MathX.roundDown(d, p));
-        
-        d = 88.123459; p = 5;
-        assertEquals("roundDown ", 88.12345, MathX.roundDown(d, p));
-        
-        d = 0; p = 2;
-        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
-        
-        d = 0; p = -1;
-        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
-        
-        d = 0.01; p = -1;
-        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
-
-        d = 199.12; p = -2;
-        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
-        
-        d = 88.123459; p = -3;
-        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
-        
-        d = 99.00000001; p = -1;
-        assertEquals("roundDown ", 90, MathX.roundDown(d, p));
-        
-        d = 100.00001; p = -2;
-        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
-        
-        d = 150.0; p = -2;
-        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
-    }
-
-    public void testRoundUp() {
-        double d = 0;
-        int p = 0;
-        
-        d = 0; p = 0;
-        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
-        
-        d = 10; p = 0;
-        assertEquals("roundUp ", 10, MathX.roundUp(d, p));
-        
-        d = 123.23; p = 0;
-        assertEquals("roundUp ", 124, MathX.roundUp(d, p));
-        
-        d = -123.23; p = 0;
-        assertEquals("roundUp ", -124, MathX.roundUp(d, p));
-        
-        d = 123.12; p = 2;
-        assertEquals("roundUp ", 123.12, MathX.roundUp(d, p));
-        
-        d = 88.123459; p = 5;
-        assertEquals("roundUp ", 88.12346, MathX.roundUp(d, p));
-        
-        d = 0; p = 2;
-        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
-        
-        d = 0; p = -1;
-        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
-        
-        d = 0.01; p = -1;
-        assertEquals("roundUp ", 10, MathX.roundUp(d, p));
-
-        d = 123.12; p = -2;
-        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
-        
-        d = 88.123459; p = -3;
-        assertEquals("roundUp ", 1000, MathX.roundUp(d, p));
-        
-        d = 49.00000001; p = -1;
-        assertEquals("roundUp ", 50, MathX.roundUp(d, p));
-        
-        d = 149.999999; p = -2;
-        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
-        
-        d = 150.0; p = -2;
-        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
-    }
-
-    public void testCeiling() {
-        double d = 0;
-        double s = 0;
-        
-        d = 0; s = 0;
-        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
-        
-        d = 1; s = 0;
-        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
-        
-        d = 0; s = 1;
-        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
-        
-        d = -1; s = 0;
-        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
-        
-        d = 0; s = -1;
-        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
-        
-        d = 10; s = 1.11;
-        assertEquals("ceiling ", 11.1, MathX.ceiling(d, s));
-        
-        d = 11.12333; s = 0.03499;
-        assertEquals("ceiling ", 11.12682, MathX.ceiling(d, s));
-        
-        d = -11.12333; s = 0.03499;
-        assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
-        
-        d = 11.12333; s = -0.03499;
-        assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
-        
-        d = -11.12333; s = -0.03499;
-        assertEquals("ceiling ", -11.12682, MathX.ceiling(d, s));
-        
-        d = 100; s = 0.001;
-        assertEquals("ceiling ", 100, MathX.ceiling(d, s));
-        
-        d = -0.001; s = -9.99;
-        assertEquals("ceiling ", -9.99, MathX.ceiling(d, s));
-        
-        d = 4.42; s = 0.05;
-        assertEquals("ceiling ", 4.45, MathX.ceiling(d, s));
-        
-        d = 0.05; s = 4.42;
-        assertEquals("ceiling ", 4.42, MathX.ceiling(d, s));
-        
-        d = 0.6666; s = 3.33;
-        assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
-        
-        d = 2d/3; s = 3.33;
-        assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
-    }
-
-    public void testFloor() {
-        double d = 0;
-        double s = 0;
-        
-        d = 0; s = 0;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = 1; s = 0;
-        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
-        
-        d = 0; s = 1;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = -1; s = 0;
-        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
-        
-        d = 0; s = -1;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = 10; s = 1.11;
-        assertEquals("floor ", 9.99, MathX.floor(d, s));
-        
-        d = 11.12333; s = 0.03499;
-        assertEquals("floor ", 11.09183, MathX.floor(d, s));
-        
-        d = -11.12333; s = 0.03499;
-        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
-        
-        d = 11.12333; s = -0.03499;
-        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
-        
-        d = -11.12333; s = -0.03499;
-        assertEquals("floor ", -11.09183, MathX.floor(d, s));
-        
-        d = 100; s = 0.001;
-        assertEquals("floor ", 100, MathX.floor(d, s));
-        
-        d = -0.001; s = -9.99;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = 4.42; s = 0.05;
-        assertEquals("floor ", 4.4, MathX.floor(d, s));
-        
-        d = 0.05; s = 4.42;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = 0.6666; s = 3.33;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-        
-        d = 2d/3; s = 3.33;
-        assertEquals("floor ", 0, MathX.floor(d, s));
-    }
-
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java
deleted file mode 100644 (file)
index 72b50da..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-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;
-/**
- * Tests for Excel function MID()
- *
- * @author Josh Micich
- */
-public final class TestMid extends TestCase {
-
-
-       private static ValueEval invokeMid(ValueEval text, ValueEval startPos, ValueEval numChars) {
-               ValueEval[] args = new ValueEval[] { text, startPos, numChars, };
-               return TextFunction.MID.evaluate(args, -1, (short)-1);
-       }
-
-       private void confirmMid(ValueEval text, ValueEval startPos, ValueEval numChars, String expected) {
-               ValueEval result = invokeMid(text, startPos, numChars);
-               assertEquals(StringEval.class, result.getClass());
-               assertEquals(expected, ((StringEval)result).getStringValue());
-       }
-
-       private void confirmMid(ValueEval text, ValueEval startPos, ValueEval numChars, ErrorEval expectedError) {
-               ValueEval result = invokeMid(text, startPos, numChars);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
-       }
-
-       public void testBasic() {
-
-               confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(4), "lact");
-       }
-
-       /**
-        * Valid cases where args are not precisely (string, int, int) but can be resolved OK.
-        */
-       public void testUnusualArgs() {
-               // startPos with fractional digits
-               confirmMid(new StringEval("galactic"), new NumberEval(3.1), new NumberEval(4), "lact");
-
-               // string startPos
-               confirmMid(new StringEval("galactic"), new StringEval("3"), new NumberEval(4), "lact");
-
-               // text (first) arg type is number, other args are strings with fractional digits
-               confirmMid(new NumberEval(123456), new StringEval("3.1"), new StringEval("2.9"), "34");
-
-               // startPos is 1x1 area ref, numChars is cell ref
-               AreaEval aeStart = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(2), } );
-               RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3));
-               confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala");
-
-               confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.instance, "");
-
-               confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.FALSE, "");
-               confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.TRUE, "l");
-               confirmMid(BlankEval.instance, new NumberEval(3), BoolEval.TRUE, "");
-
-       }
-
-       /**
-        * Extreme values for startPos and numChars
-        */
-       public void testExtremes() {
-               confirmMid(new StringEval("galactic"), new NumberEval(4), new NumberEval(400), "actic");
-
-               confirmMid(new StringEval("galactic"), new NumberEval(30), new NumberEval(4), "");
-               confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(0), "");
-       }
-
-       /**
-        * All sorts of ways to make MID return defined errors.
-        */
-       public void testErrors() {
-               confirmMid(ErrorEval.NAME_INVALID, new NumberEval(3), new NumberEval(4), ErrorEval.NAME_INVALID);
-               confirmMid(new StringEval("galactic"), ErrorEval.NAME_INVALID, new NumberEval(4), ErrorEval.NAME_INVALID);
-               confirmMid(new StringEval("galactic"), new NumberEval(3), ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
-               confirmMid(new StringEval("galactic"), ErrorEval.DIV_ZERO, ErrorEval.NAME_INVALID, ErrorEval.DIV_ZERO);
-
-               confirmMid(new StringEval("galactic"), BlankEval.instance, new NumberEval(3.1), ErrorEval.VALUE_INVALID);
-
-               confirmMid(new StringEval("galactic"), new NumberEval(0), new NumberEval(4), ErrorEval.VALUE_INVALID);
-               confirmMid(new StringEval("galactic"), new NumberEval(1), new NumberEval(-1), ErrorEval.VALUE_INVALID);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestNper.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestNper.java
deleted file mode 100644 (file)
index 99fb4de..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Tests for {@link FinanceFunction#NPER}
- *
- * @author Josh Micich
- */
-public final class TestNper extends TestCase {
-       public void testSimpleEvaluate() {
-
-               ValueEval[] args = {
-                       new NumberEval(0.05),
-                       new NumberEval(250),
-                       new NumberEval(-1000),
-               };
-               ValueEval result = FinanceFunction.NPER.evaluate(args, 0, (short)0);
-
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(4.57353557, ((NumberEval)result).getNumberValue(), 0.00000001);
-       }
-
-       public void testEvaluate_bug_45732() {
-               HSSFWorkbook wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("Sheet1");
-               HSSFCell cell = sheet.createRow(0).createCell(0);
-
-               cell.setCellFormula("NPER(12,4500,100000,100000)");
-               cell.setCellValue(15.0);
-               assertEquals("NPER(12,4500,100000,100000)", cell.getCellFormula());
-               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
-               assertEquals(15.0, cell.getNumericCellValue(), 0.0);
-
-               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-               fe.evaluateFormulaCell(cell);
-               assertEquals(HSSFCell.CELL_TYPE_ERROR, cell.getCachedFormulaResultType());
-               assertEquals(HSSFErrorConstants.ERROR_NUM, cell.getErrorCellValue());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestOffset.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestOffset.java
deleted file mode 100644 (file)
index 7002408..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.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.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) {
-               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);
-               confirmDoubleConvert(+1.01, +1);
-               confirmDoubleConvert(+1.00, +1);
-               confirmDoubleConvert(+0.99,  0);
-               confirmDoubleConvert(+0.01,  0);
-               confirmDoubleConvert( 0.00,  0);
-               confirmDoubleConvert(-0.01, -1);
-               confirmDoubleConvert(-0.99, -1);
-               confirmDoubleConvert(-1.00, -1);
-               confirmDoubleConvert(-1.01, -2);
-               confirmDoubleConvert(-1.99, -2);
-               confirmDoubleConvert(-2.00, -2);
-               confirmDoubleConvert(-2.01, -3);
-       }
-
-       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));
-               lor = lor.normaliseAndTranslate(16300);
-               assertTrue(lor.isOutOfBounds(0, 16383));
-               assertFalse(lor.isOutOfBounds(0, 65535));
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java
deleted file mode 100644 (file)
index cac4bde..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
-
-/**
- * @author Josh Micich
- */
-public final class TestPmt extends TestCase {
-
-       private static void confirm(double expected, NumberEval ne) {
-               // only asserting accuracy to 4 fractional digits
-               assertEquals(expected, ne.getNumberValue(), 0.00005);
-       }
-       private static ValueEval invoke(ValueEval[] args) {
-               return FinanceFunction.PMT.evaluate(args, -1, (short)-1);
-       }
-       /**
-        * Invocation when not expecting an error result
-        */
-       private static NumberEval invokeNormal(ValueEval[] args) {
-               ValueEval ev = invoke(args);
-               if(ev instanceof ErrorEval) {
-                       throw new AssertionFailedError("Normal evaluation failed with error code: "
-                                       + ev.toString());
-               }
-               return (NumberEval) ev;
-       }
-
-       private static void confirm(double expected, double rate, double nper, double pv, double fv, boolean isBeginning) {
-               ValueEval[] args = {
-                               new NumberEval(rate),
-                               new NumberEval(nper),
-                               new NumberEval(pv),
-                               new NumberEval(fv),
-                               new NumberEval(isBeginning ? 1 : 0),
-               };
-               confirm(expected, invokeNormal(args));
-       }
-
-
-       public void testBasic() {
-               confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
-               confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
-       }
-
-       public void test3args() {
-
-               ValueEval[] args = {
-                               new NumberEval(0.005),
-                               new NumberEval(24),
-                               new NumberEval(1000),
-               };
-               ValueEval ev = invoke(args);
-               if(ev instanceof ErrorEval) {
-                       ErrorEval err = (ErrorEval) ev;
-                       if(err.getErrorCode() == HSSFErrorConstants.ERROR_VALUE) {
-                               throw new AssertionFailedError("Identified bug 44691");
-                       }
-               }
-
-               confirm(-44.3206, invokeNormal(args));
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPoisson.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPoisson.java
deleted file mode 100644 (file)
index f09a25f..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Tests for Excel function POISSON(x,mean,cumulative)
- * @author Kalpesh Parmar
- */
-public class TestPoisson extends TestCase {
-
-    private static final double DELTA = 1E-15;
-
-    private static ValueEval invokePoisson(double x, double mean, boolean cumulative)
-    {
-
-        ValueEval[] valueEvals = new ValueEval[3];
-        valueEvals[0] = new NumberEval(x);
-        valueEvals[1] = new NumberEval(mean);
-        valueEvals[2] = BoolEval.valueOf(cumulative);
-
-        return NumericFunction.POISSON.evaluate(valueEvals,-1,-1);
-       }
-
-    public void testCumulativeProbability()
-    {
-        double x = 1;
-        double mean = 0.2;
-        double result = 0.9824769036935787; // known result
-
-        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
-
-        assertEquals(myResult.getNumberValue(), result, DELTA);
-    }
-
-    public void testNonCumulativeProbability()
-    {
-        double x = 0;
-        double mean = 0.2;
-        double result = 0.8187307530779818; // known result
-        
-        NumberEval myResult = (NumberEval)invokePoisson(x,mean,false);
-
-        assertEquals(myResult.getNumberValue(), result, DELTA);
-    }
-
-    public void testNegativeMean()
-    {
-        double x = 0;
-        double mean = -0.2;
-
-        ErrorEval myResult = (ErrorEval)invokePoisson(x,mean,false);
-
-        assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), myResult.getErrorCode());
-    }
-
-    public void testNegativeX()
-    {
-        double x = -1;
-        double mean = 0.2;
-
-        ErrorEval myResult = (ErrorEval)invokePoisson(x,mean,false);
-
-        assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), myResult.getErrorCode());    
-    }
-
-
-
-    public void testXAsDecimalNumber()
-    {
-        double x = 1.1;
-        double mean = 0.2;
-        double result = 0.9824769036935787; // known result
-
-        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
-
-        assertEquals(myResult.getNumberValue(), result, DELTA);
-    }
-
-    public void testXZeroMeanZero()
-    {
-        double x = 0;
-        double mean = 0;
-        double result = 1; // known result in excel
-
-        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
-
-        assertEquals(myResult.getNumberValue(), result, DELTA);
-    }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestRoundFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestRoundFuncs.java
deleted file mode 100644 (file)
index d3fa564..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-
-/**
- * Test cases for ROUND(), ROUNDUP(), ROUNDDOWN()
- *
- * @author Josh Micich
- */
-public final class TestRoundFuncs extends TestCase {
-       private static final NumericFunction F = null;
-       public void testRounddownWithStringArg() {
-
-               ValueEval strArg = new StringEval("abc");
-               ValueEval[] args = { strArg, new NumberEval(2), };
-               ValueEval result = F.ROUNDDOWN.evaluate(args, -1, (short)-1);
-               assertEquals(ErrorEval.VALUE_INVALID, result);
-       }
-
-       public void testRoundupWithStringArg() {
-
-               ValueEval strArg = new StringEval("abc");
-               ValueEval[] args = { strArg, new NumberEval(2), };
-               ValueEval result = F.ROUNDUP.evaluate(args, -1, (short)-1);
-               assertEquals(ErrorEval.VALUE_INVALID, result);
-       }
-
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestRowCol.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestRowCol.java
deleted file mode 100644 (file)
index 532e768..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Tests for ROW(), ROWS(), COLUMN(), COLUMNS()
- *
- * @author Josh Micich
- */
-public final class TestRowCol extends TestCase {
-
-       public void testCol() {
-               Function target = new Column();
-               {
-                       ValueEval[] args = { EvalFactory.createRefEval("C5"), };
-                       double actual = NumericFunctionInvoker.invoke(target, args);
-                       assertEquals(3, actual, 0D);
-               }
-               {
-                       ValueEval[] args = { EvalFactory.createAreaEval("E2:H12", new ValueEval[44]), };
-                       double actual = NumericFunctionInvoker.invoke(target, args);
-                       assertEquals(5, actual, 0D);
-               }
-       }
-
-       public void testRow() {
-               Function target = new RowFunc();
-               {
-                       ValueEval[] args = { EvalFactory.createRefEval("C5"), };
-                       double actual = NumericFunctionInvoker.invoke(target, args);
-                       assertEquals(5, actual, 0D);
-               }
-               {
-                       ValueEval[] args = { EvalFactory.createAreaEval("E2:H12", new ValueEval[44]), };
-                       double actual = NumericFunctionInvoker.invoke(target, args);
-                       assertEquals(2, actual, 0D);
-               }
-       }
-
-       public void testColumns() {
-
-               confirmColumnsFunc("A1:F1", 6, 1);
-               confirmColumnsFunc("A1:C2", 3, 2);
-               confirmColumnsFunc("A1:B3", 2, 3);
-               confirmColumnsFunc("A1:A6", 1, 6);
-
-               ValueEval[] args = { EvalFactory.createRefEval("C5"), };
-               double actual = NumericFunctionInvoker.invoke(new Columns(), args);
-               assertEquals(1, actual, 0D);
-       }
-
-       public void testRows() {
-
-               confirmRowsFunc("A1:F1", 6, 1);
-               confirmRowsFunc("A1:C2", 3, 2);
-               confirmRowsFunc("A1:B3", 2, 3);
-               confirmRowsFunc("A1:A6", 1, 6);
-
-               ValueEval[] args = { EvalFactory.createRefEval("C5"), };
-               double actual = NumericFunctionInvoker.invoke(new Rows(), args);
-               assertEquals(1, actual, 0D);
-       }
-
-       private static void confirmRowsFunc(String areaRefStr, int nCols, int nRows) {
-               ValueEval[] args = { EvalFactory.createAreaEval(areaRefStr, new ValueEval[nCols * nRows]), };
-
-               double actual = NumericFunctionInvoker.invoke(new Rows(), args);
-               assertEquals(nRows, actual, 0D);
-       }
-
-
-       private static void confirmColumnsFunc(String areaRefStr, int nCols, int nRows) {
-               ValueEval[] args = { EvalFactory.createAreaEval(areaRefStr, new ValueEval[nCols * nRows]), };
-
-               double actual = NumericFunctionInvoker.invoke(new Columns(), args);
-               assertEquals(nCols, actual, 0D);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java
deleted file mode 100644 (file)
index 3562a67..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
-*/
-/*
- * Created on May 30, 2005
- *
- */
-package org.apache.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.EvaluationException;
-
-
-/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *
- */
-public class TestStatsLib extends AbstractNumericTestCase {
-
-    public void testDevsq() {
-        double[] v = null;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        d = StatsLib.devsq(v);
-        x = 82.5;
-        assertEquals("devsq ", x, d);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        d = StatsLib.devsq(v);
-        x = 0;
-        assertEquals("devsq ", x, d);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        d = StatsLib.devsq(v);
-        x = 0;
-        assertEquals("devsq ", x, d);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        d = StatsLib.devsq(v);
-        x = 2.5;
-        assertEquals("devsq ", x, d);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        d = StatsLib.devsq(v);
-        x = 10953.7416965767;
-        assertEquals("devsq ", x, d);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.devsq(v);
-        x = 82.5;
-        assertEquals("devsq ", x, d);
-    }
-
-    public void testKthLargest() {
-        double[] v = null;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        d = StatsLib.kthLargest(v, 3);
-        x = 8;
-        assertEquals("kthLargest ", x, d);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        d = StatsLib.kthLargest(v, 3);
-        x = 1;
-        assertEquals("kthLargest ", x, d);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        d = StatsLib.kthLargest(v, 3);
-        x = 0;
-        assertEquals("kthLargest ", x, d);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        d = StatsLib.kthLargest(v, 3);
-        x = 2;
-        assertEquals("kthLargest ", x, d);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        d = StatsLib.kthLargest(v, 3);
-        x = 5.37828;
-        assertEquals("kthLargest ", x, d);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.kthLargest(v, 3);
-        x = -3;
-        assertEquals("kthLargest ", x, d);
-    }
-
-    public void testKthSmallest() {
-    }
-
-    public void testAvedev() {
-        double[] v = null;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        d = StatsLib.avedev(v);
-        x = 2.5;
-        assertEquals("avedev ", x, d);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        d = StatsLib.avedev(v);
-        x = 0;
-        assertEquals("avedev ", x, d);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        d = StatsLib.avedev(v);
-        x = 0;
-        assertEquals("avedev ", x, d);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        d = StatsLib.avedev(v);
-        x = 0.5;
-        assertEquals("avedev ", x, d);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        d = StatsLib.avedev(v);
-        x = 36.42176053333;
-        assertEquals("avedev ", x, d);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.avedev(v);
-        x = 2.5;
-        assertEquals("avedev ", x, d);
-    }
-
-    public void testMedian() {
-        double[] v = null;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        d = StatsLib.median(v);
-        x = 5.5;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        d = StatsLib.median(v);
-        x = 1;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        d = StatsLib.median(v);
-        x = 0;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        d = StatsLib.median(v);
-        x = 1.5;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        d = StatsLib.median(v);
-        x = 5.37828;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.median(v);
-        x = -5.5;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.median(v);
-        x = -6;
-        assertEquals("median ", x, d);
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9};
-        d = StatsLib.median(v);
-        x = 5;
-        assertEquals("median ", x, d);
-    }
-
-    public void testMode() {
-        double[] v;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        confirmMode(v, null);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        confirmMode(v, 1.0);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        confirmMode(v, 0.0);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        confirmMode(v, 1.0);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        confirmMode(v, null);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        confirmMode(v, null);
-        
-        v = new double[] {1,2,3,4,1,1,1,1,0,0,0,0,0};
-        confirmMode(v, 1.0);
-        
-        v = new double[] {0,1,2,3,4,1,1,1,0,0,0,0,1};
-        confirmMode(v, 0.0);
-    }
-    private static void confirmMode(double[] v, double expectedResult) {
-       confirmMode(v, new Double(expectedResult));
-    }
-    private static void confirmMode(double[] v, Double expectedResult) {
-       double actual;
-               try {
-                       actual = Mode.evaluate(v);
-                       if (expectedResult == null) {
-                               throw new AssertionFailedError("Expected N/A exception was not thrown");
-                       }
-               } catch (EvaluationException e) {
-                       if (expectedResult == null) {
-                               assertEquals(ErrorEval.NA, e.getErrorEval());
-                               return;
-                       }
-                       throw new RuntimeException(e);
-               }
-       assertEquals("mode", expectedResult.doubleValue(), actual);
-    }
-    
-
-    public void testStddev() {
-        double[] v = null;
-        double d, x = 0;
-        
-        v = new double[] {1,2,3,4,5,6,7,8,9,10};
-        d = StatsLib.stdev(v);
-        x = 3.02765035410;
-        assertEquals("stdev ", x, d);
-        
-        v = new double[] {1,1,1,1,1,1,1,1,1,1};
-        d = StatsLib.stdev(v);
-        x = 0;
-        assertEquals("stdev ", x, d);
-        
-        v = new double[] {0,0,0,0,0,0,0,0,0,0};
-        d = StatsLib.stdev(v);
-        x = 0;
-        assertEquals("stdev ", x, d);
-        
-        v = new double[] {1,2,1,2,1,2,1,2,1,2};
-        d = StatsLib.stdev(v);
-        x = 0.52704627669;
-        assertEquals("stdev ", x, d);
-        
-        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
-        d = StatsLib.stdev(v);
-        x = 52.33006233652;
-        assertEquals("stdev ", x, d);
-        
-        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
-        d = StatsLib.stdev(v);
-        x = 3.02765035410;
-        assertEquals("stdev ", x, d);
-    }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSubtotal.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSubtotal.java
deleted file mode 100644 (file)
index 974f897..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link Subtotal}
- *
- * @author Paul Tomlin
- */
-public final class TestSubtotal extends TestCase {
-       private static final int FUNCTION_AVERAGE = 1;
-       private static final int FUNCTION_COUNT = 2;
-       private static final int FUNCTION_MAX = 4;
-       private static final int FUNCTION_MIN = 5;
-       private static final int FUNCTION_PRODUCT = 6;
-       private static final int FUNCTION_STDEV = 7;
-       private static final int FUNCTION_SUM = 9;
-
-       private static final double[] TEST_VALUES0 = {
-               1, 2,
-               3, 4,
-               5, 6,
-               7, 8,
-               9, 10
-       };
-
-       private static void confirmSubtotal(int function, double expected) {
-               ValueEval[] values = new ValueEval[TEST_VALUES0.length];
-               for (int i = 0; i < TEST_VALUES0.length; i++) {
-                       values[i] = new NumberEval(TEST_VALUES0[i]);
-               }
-
-               AreaEval arg1 = EvalFactory.createAreaEval("C1:D5", values);
-               ValueEval args[] = { new NumberEval(function), arg1 };
-
-               ValueEval result = new Subtotal().evaluate(args, 0, 0);
-
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(expected, ((NumberEval) result).getNumberValue(), 0.0);
-       }
-
-       public void testBasics() {
-               confirmSubtotal(FUNCTION_SUM, 55.0);
-               confirmSubtotal(FUNCTION_AVERAGE, 5.5);
-               confirmSubtotal(FUNCTION_COUNT, 10.0);
-               confirmSubtotal(FUNCTION_MAX, 10.0);
-               confirmSubtotal(FUNCTION_MIN, 1.0);
-               confirmSubtotal(FUNCTION_PRODUCT, 3628800.0);
-               confirmSubtotal(FUNCTION_STDEV, 3.0276503540974917);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumif.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumif.java
deleted file mode 100644 (file)
index ff611ec..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Test cases for SUMPRODUCT()
- *
- * @author Josh Micich
- */
-public final class TestSumif extends TestCase {
-       private static final NumberEval _30 = new NumberEval(30);
-       private static final NumberEval _40 = new NumberEval(40);
-       private static final NumberEval _50 = new NumberEval(50);
-       private static final NumberEval _60 = new NumberEval(60);
-
-       private static ValueEval invokeSumif(int rowIx, int colIx, ValueEval...args) {
-               return new Sumif().evaluate(args, rowIx, colIx);
-       }
-       private static void confirmDouble(double expected, ValueEval actualEval) {
-               if(!(actualEval instanceof NumericValueEval)) {
-                       throw new AssertionFailedError("Expected numeric result");
-               }
-               NumericValueEval nve = (NumericValueEval)actualEval;
-               assertEquals(expected, nve.getNumberValue(), 0);
-       }
-
-       public void testBasic() {
-               ValueEval[] arg0values = new ValueEval[] { _30, _30, _40, _40, _50, _50  };
-               ValueEval[] arg2values = new ValueEval[] { _30, _40, _50, _60, _60, _60 };
-
-               AreaEval arg0;
-               AreaEval arg2;
-
-               arg0 = EvalFactory.createAreaEval("A3:B5", arg0values);
-               arg2 = EvalFactory.createAreaEval("D1:E3", arg2values);
-
-               confirm(60.0, arg0, new NumberEval(30.0));
-               confirm(70.0, arg0, new NumberEval(30.0), arg2);
-               confirm(100.0, arg0, new StringEval(">45"));
-
-       }
-       private static void confirm(double expectedResult, ValueEval...args) {
-               confirmDouble(expectedResult, invokeSumif(-1, -1, args));
-       }
-
-
-       /**
-        * test for bug observed near svn r882931
-        */
-       public void testCriteriaArgRange() {
-               ValueEval[] arg0values = new ValueEval[] { _50, _60, _50, _50, _50, _30,  };
-               ValueEval[] arg1values = new ValueEval[] { _30, _40, _50, _60,  };
-
-               AreaEval arg0;
-               AreaEval arg1;
-               ValueEval ve;
-
-               arg0 = EvalFactory.createAreaEval("A3:B5", arg0values);
-               arg1 = EvalFactory.createAreaEval("A2:D2", arg1values); // single row range
-
-               ve = invokeSumif(0, 2, arg0, arg1);  // invoking from cell C1
-               if (ve instanceof NumberEval) {
-                       NumberEval ne = (NumberEval) ve;
-                       if (ne.getNumberValue() == 30.0) {
-                               throw new AssertionFailedError("identified error in SUMIF - criteria arg not evaluated properly");
-                       }
-               }
-
-               confirmDouble(200, ve);
-
-               arg0 = EvalFactory.createAreaEval("C1:D3", arg0values);
-               arg1 = EvalFactory.createAreaEval("B1:B4", arg1values); // single column range
-
-               ve = invokeSumif(3, 0, arg0, arg1); // invoking from cell A4
-
-               confirmDouble(60, ve);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java
deleted file mode 100644 (file)
index 63d1088..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
-import org.apache.poi.hssf.record.formula.eval.RefEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Test cases for SUMPRODUCT()
- *
- * @author Josh Micich
- */
-public final class TestSumproduct extends TestCase {
-
-       private static ValueEval invokeSumproduct(ValueEval[] args) {
-               // srcCellRow and srcCellColumn are ignored by SUMPRODUCT
-               return new Sumproduct().evaluate(args, -1, (short)-1);
-       }
-       private static void confirmDouble(double expected, ValueEval actualEval) {
-               if(!(actualEval instanceof NumericValueEval)) {
-                       fail("Expected numeric result");
-               }
-               NumericValueEval nve = (NumericValueEval)actualEval;
-               assertEquals(expected, nve.getNumberValue(), 0);
-       }
-
-       public void testScalarSimple() {
-
-               RefEval refEval = EvalFactory.createRefEval("A1", new NumberEval(3));
-               ValueEval[] args = {
-                       refEval,
-                       new NumberEval(2),
-               };
-               ValueEval result = invokeSumproduct(args);
-               confirmDouble(6D, result);
-       }
-
-       public void testAreaSimple() {
-               ValueEval[] aValues = {
-                       new NumberEval(2),
-                       new NumberEval(4),
-                       new NumberEval(5),
-               };
-               ValueEval[] bValues = {
-                       new NumberEval(3),
-                       new NumberEval(6),
-                       new NumberEval(7),
-               };
-               AreaEval aeA = EvalFactory.createAreaEval("A1:A3", aValues);
-               AreaEval aeB = EvalFactory.createAreaEval("B1:B3", bValues);
-
-               ValueEval[] args = { aeA, aeB, };
-               ValueEval result = invokeSumproduct(args);
-               confirmDouble(65D, result);
-       }
-
-       /**
-        * For scalar products, the terms may be 1x1 area refs
-        */
-       public void testOneByOneArea() {
-
-               AreaEval ae = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(7), });
-
-               ValueEval[] args = {
-                               ae,
-                               new NumberEval(2),
-                       };
-               ValueEval result = invokeSumproduct(args);
-               confirmDouble(14D, result);
-       }
-
-       public void testMismatchAreaDimensions() {
-
-               AreaEval aeA = EvalFactory.createAreaEval("A1:A3", new ValueEval[3]);
-               AreaEval aeB = EvalFactory.createAreaEval("B1:D1", new ValueEval[3]);
-
-               ValueEval[] args;
-               args = new ValueEval[] { aeA, aeB, };
-               assertEquals(ErrorEval.VALUE_INVALID, invokeSumproduct(args));
-
-               args = new ValueEval[] { aeA, new NumberEval(5), };
-               assertEquals(ErrorEval.VALUE_INVALID, invokeSumproduct(args));
-       }
-
-       public void testAreaWithErrorCell() {
-               ValueEval[] aValues = {
-                       ErrorEval.REF_INVALID,
-                       null,
-               };
-               AreaEval aeA = EvalFactory.createAreaEval("A1:A2", aValues);
-               AreaEval aeB = EvalFactory.createAreaEval("B1:B2", new ValueEval[2]);
-
-               ValueEval[] args = { aeA, aeB, };
-               assertEquals(ErrorEval.REF_INVALID, invokeSumproduct(args));
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java
deleted file mode 100644 (file)
index 9d77b3d..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Test cases for Excel function T()
- *
- * @author Josh Micich
- */
-public final class TestTFunc extends TestCase {
-
-       /**
-        * @return the result of calling function T() with the specified argument
-        */
-       private static ValueEval invokeT(ValueEval arg) {
-               ValueEval[] args = { arg, };
-               ValueEval result = new T().evaluate(args, -1, (short)-1);
-               assertNotNull("result may never be null", result);
-               return result;
-       }
-       /**
-        * Simulates call: T(A1)
-        * where cell A1 has the specified innerValue
-        */
-       private ValueEval invokeTWithReference(ValueEval innerValue) {
-               ValueEval arg = EvalFactory.createRefEval("$B$2", innerValue);
-               return invokeT(arg);
-       }
-
-       private static void confirmText(String text) {
-               ValueEval arg = new StringEval(text);
-               ValueEval eval = invokeT(arg);
-               StringEval se = (StringEval) eval;
-               assertEquals(text, se.getStringValue());
-       }
-
-       public void testTextValues() {
-
-               confirmText("abc");
-               confirmText("");
-               confirmText(" ");
-               confirmText("~");
-               confirmText("123");
-               confirmText("TRUE");
-       }
-
-       private static void confirmError(ValueEval arg) {
-               ValueEval eval = invokeT(arg);
-               assertTrue(arg == eval);
-       }
-
-       public void testErrorValues() {
-
-               confirmError(ErrorEval.VALUE_INVALID);
-               confirmError(ErrorEval.NA);
-               confirmError(ErrorEval.REF_INVALID);
-       }
-
-       private static void confirmString(ValueEval eval, String expected) {
-               assertTrue(eval instanceof StringEval);
-               assertEquals(expected, ((StringEval)eval).getStringValue());
-       }
-
-       private static void confirmOther(ValueEval arg) {
-               ValueEval eval = invokeT(arg);
-               confirmString(eval, "");
-       }
-
-       public void testOtherValues() {
-               confirmOther(new NumberEval(2));
-               confirmOther(BoolEval.FALSE);
-               confirmOther(BlankEval.instance);  // can this particular case be verified?
-       }
-
-       public void testRefValues() {
-               ValueEval eval;
-
-               eval = invokeTWithReference(new StringEval("def"));
-               confirmString(eval, "def");
-               eval = invokeTWithReference(new StringEval(" "));
-               confirmString(eval, " ");
-
-               eval = invokeTWithReference(new NumberEval(2));
-               confirmString(eval, "");
-               eval = invokeTWithReference(BoolEval.TRUE);
-               confirmString(eval, "");
-
-               eval = invokeTWithReference(ErrorEval.NAME_INVALID);
-               assertTrue(eval == ErrorEval.NAME_INVALID);
-       }
-
-       public void testAreaArg() {
-               ValueEval[] areaValues = new ValueEval[] {
-                       new StringEval("abc"), new StringEval("def"),
-                       new StringEval("ghi"), new StringEval("jkl"),
-               };
-               AreaEval ae = EvalFactory.createAreaEval("C10:D11", areaValues);
-
-               ValueEval ve;
-               ve = invokeT(ae);
-               confirmString(ve, "abc");
-
-               areaValues[0] = new NumberEval(5.0);
-               ve = invokeT(ae);
-               confirmString(ve, "");
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestText.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestText.java
deleted file mode 100644 (file)
index f56132c..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.text.DecimalFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-
-import junit.framework.TestCase;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-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.eval.StringEval;
-
-/**
- * Test case for TEXT()
- *
- * @author Stephen Wolke (smwolke at geistig.com)
- */
-public final class TestText extends TestCase {
-       private static final TextFunction T = null;
-
-       public void testTextWithStringFirstArg() {
-
-               ValueEval strArg = new StringEval("abc");
-               ValueEval formatArg = new StringEval("abc");
-               ValueEval[] args = { strArg, formatArg };
-               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
-               assertEquals(ErrorEval.VALUE_INVALID, result);
-       }
-
-       public void testTextWithDeciamlFormatSecondArg() {
-
-               ValueEval numArg = new NumberEval(321321.321);
-               ValueEval formatArg = new StringEval("#,###.00000");
-               ValueEval[] args = { numArg, formatArg };
-               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
-               char groupSeparator = new DecimalFormatSymbols(Locale.getDefault()).getGroupingSeparator();
-               char decimalSeparator = new DecimalFormatSymbols(Locale.getDefault()).getDecimalSeparator();
-               ValueEval testResult = new StringEval("321" + groupSeparator + "321" + decimalSeparator + "32100");
-               assertEquals(testResult.toString(), result.toString());
-               numArg = new NumberEval(321.321);
-               formatArg = new StringEval("00000.00000");
-               args[0] = numArg;
-               args[1] = formatArg;
-               result = T.TEXT.evaluate(args, -1, (short)-1);
-               testResult = new StringEval("00321" + decimalSeparator + "32100");
-               assertEquals(testResult.toString(), result.toString());
-
-               formatArg = new StringEval("$#.#");
-               args[1] = formatArg;
-               result = T.TEXT.evaluate(args, -1, (short)-1);
-               testResult = new StringEval("$321" + decimalSeparator + "3");
-               assertEquals(testResult.toString(), result.toString());
-       }
-
-       public void testTextWithFractionFormatSecondArg() {
-
-               ValueEval numArg = new NumberEval(321.321);
-               ValueEval formatArg = new StringEval("# #/#");
-               ValueEval[] args = { numArg, formatArg };
-               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
-               ValueEval testResult = new StringEval("321 1/3");
-               assertEquals(testResult.toString(), result.toString());
-
-               formatArg = new StringEval("# #/##");
-               args[1] = formatArg;
-               result = T.TEXT.evaluate(args, -1, (short)-1);
-               testResult = new StringEval("321 26/81");
-               assertEquals(testResult.toString(), result.toString());
-
-               formatArg = new StringEval("#/##");
-               args[1] = formatArg;
-               result = T.TEXT.evaluate(args, -1, (short)-1);
-               testResult = new StringEval("26027/81");
-               assertEquals(testResult.toString(), result.toString());
-       }
-
-       public void testTextWithDateFormatSecondArg() {
-
-               ValueEval numArg = new NumberEval(321.321);
-               ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
-               ValueEval[] args = { numArg, formatArg };
-               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
-               ValueEval testResult = new StringEval("16:11:1900 07:42:14");
-               assertEquals(testResult.toString(), result.toString());
-
-               // this line is intended to compute how "November" would look like in the current locale
-               String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime());
-
-               formatArg = new StringEval("MMMM dd, yyyy");
-               args[1] = formatArg;
-               result = T.TEXT.evaluate(args, -1, (short)-1);
-               testResult = new StringEval(november + " 16, 1900");
-               assertEquals(testResult.toString(), result.toString());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTime.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTime.java
deleted file mode 100644 (file)
index bfd1747..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import java.util.regex.Pattern;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFDataFormat;
-import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Tests for {@link TimeFunc}
- *
- * @author @author Steven Butler (sebutler @ gmail dot com)
- */
-public final class TestTime extends TestCase {
-
-       private static final int SECONDS_PER_MINUTE = 60;
-       private static final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
-       private static final double SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;
-       private HSSFCell cell11;
-       private HSSFFormulaEvaluator evaluator;
-       private HSSFWorkbook wb;
-       private HSSFDataFormatter form;
-       private HSSFCellStyle style;
-
-       public void setUp() {
-               wb = new HSSFWorkbook();
-               HSSFSheet sheet = wb.createSheet("new sheet");
-               style = wb.createCellStyle();
-               HSSFDataFormat fmt = wb.createDataFormat();
-               style.setDataFormat(fmt.getFormat("hh:mm:ss"));
-
-               cell11 = sheet.createRow(0).createCell(0);
-               form = new HSSFDataFormatter();
-
-               evaluator = new HSSFFormulaEvaluator(wb);
-       }
-
-       public void testSomeArgumentsMissing() {
-               confirm("00:00:00", "TIME(, 0, 0)");
-               confirm("12:00:00", "TIME(12, , )");
-       }
-
-       public void testValid() {
-               confirm("00:00:01", 0, 0, 1);
-               confirm("00:01:00", 0, 1, 0);
-
-               confirm("00:00:00", 0, 0, 0);
-
-               confirm("01:00:00", 1, 0, 0);
-               confirm("12:00:00", 12, 0, 0);
-               confirm("23:00:00", 23, 0, 0);
-               confirm("00:00:00", 24, 0, 0);
-               confirm("01:00:00", 25, 0, 0);
-               confirm("00:00:00", 48, 0, 0);
-               confirm("06:00:00", 6, 0, 0);
-               confirm("06:01:00", 6, 1, 0);
-               confirm("06:30:00", 6, 30, 0);
-
-               confirm("06:59:00", 6, 59, 0);
-               confirm("07:00:00", 6, 60, 0);
-               confirm("07:01:00", 6, 61, 0);
-               confirm("08:00:00", 6, 120, 0);
-               confirm("06:00:00", 6, 1440, 0);
-               confirm("18:49:00", 18, 49, 0);
-               confirm("18:49:01", 18, 49, 1);
-               confirm("18:49:30", 18, 49, 30);
-               confirm("18:49:59", 18, 49, 59);
-               confirm("18:50:00", 18, 49, 60);
-               confirm("18:50:01", 18, 49, 61);
-               confirm("18:50:59", 18, 49, 119);
-               confirm("18:51:00", 18, 49, 120);
-               confirm("03:55:07", 18, 49, 32767);
-               confirm("12:08:01", 18, 32767, 61);
-               confirm("07:50:01", 32767, 49, 61);
-       }
-       private void confirm(String expectedTimeStr, int inH, int inM, int inS) {
-               confirm(expectedTimeStr, "TIME(" + inH + "," + inM + "," + inS + ")");
-       }
-
-       private void confirm(String expectedTimeStr, String formulaText) {
-//             System.out.println("=" + formulaText);
-               String[] parts = Pattern.compile(":").split(expectedTimeStr);
-               int expH = Integer.parseInt(parts[0]);
-               int expM = Integer.parseInt(parts[1]);
-               int expS = Integer.parseInt(parts[2]);
-
-               double expectedValue = (expH*SECONDS_PER_HOUR + expM*SECONDS_PER_MINUTE + expS)/SECONDS_PER_DAY;
-
-               cell11.setCellFormula(formulaText);
-               cell11.setCellStyle(style);
-               evaluator.clearAllCachedResultValues();
-
-               double actualValue = evaluator.evaluate(cell11).getNumberValue();
-               assertEquals(expectedValue, actualValue, 0.0);
-
-               String actualText = form.formatCellValue(cell11, evaluator);
-               assertEquals(expectedTimeStr, actualText);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrim.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrim.java
deleted file mode 100644 (file)
index 5fd7173..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-/**
- * Tests for Excel function TRIM()
- *
- * @author Josh Micich
- */
-public final class TestTrim extends TestCase {
-
-
-       private static ValueEval invokeTrim(ValueEval text) {
-               ValueEval[] args = new ValueEval[] { text, };
-               return TextFunction.TRIM.evaluate(args, -1, (short)-1);
-       }
-
-       private void confirmTrim(ValueEval text, String expected) {
-               ValueEval result = invokeTrim(text);
-               assertEquals(StringEval.class, result.getClass());
-               assertEquals(expected, ((StringEval)result).getStringValue());
-       }
-
-       private void confirmTrim(ValueEval text, ErrorEval expectedError) {
-               ValueEval result = invokeTrim(text);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
-       }
-
-       public void testBasic() {
-
-               confirmTrim(new StringEval(" hi "), "hi");
-               confirmTrim(new StringEval("hi "), "hi");
-               confirmTrim(new StringEval("  hi"), "hi");
-               confirmTrim(new StringEval(" hi there  "), "hi there");
-               confirmTrim(new StringEval(""), "");
-               confirmTrim(new StringEval("   "), "");
-       }
-
-       /**
-        * Valid cases where text arg is not exactly a string
-        */
-       public void testUnusualArgs() {
-
-               // text (first) arg type is number, other args are strings with fractional digits
-               confirmTrim(new NumberEval(123456), "123456");
-               confirmTrim(BoolEval.FALSE, "FALSE");
-               confirmTrim(BoolEval.TRUE, "TRUE");
-               confirmTrim(BlankEval.instance, "");
-       }
-
-       public void testErrors() {
-               confirmTrim(ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrunc.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrunc.java
deleted file mode 100644 (file)
index ef42d1c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-
-/**
- * Test case for TRUNC()
- *
- * @author Stephen Wolke (smwolke at geistig.com)
- */
-public final class TestTrunc extends AbstractNumericTestCase {
-       private static final NumericFunction F = null;
-       public void testTruncWithStringArg() {
-
-               ValueEval strArg = new StringEval("abc");
-               ValueEval[] args = { strArg, new NumberEval(2) };
-               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
-               assertEquals(ErrorEval.VALUE_INVALID, result);
-       }
-
-       public void testTruncWithWholeNumber() {
-               ValueEval[] args = { new NumberEval(200), new NumberEval(2) };
-               @SuppressWarnings("static-access")
-               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
-               assertEquals("TRUNC", (new NumberEval(200d)).getNumberValue(), ((NumberEval)result).getNumberValue());
-       }
-       
-       public void testTruncWithDecimalNumber() {
-               ValueEval[] args = { new NumberEval(2.612777), new NumberEval(3) };
-               @SuppressWarnings("static-access")
-               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
-               assertEquals("TRUNC", (new NumberEval(2.612d)).getNumberValue(), ((NumberEval)result).getNumberValue());
-       }
-       
-       public void testTruncWithDecimalNumberOneArg() {
-               ValueEval[] args = { new NumberEval(2.612777) };
-               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
-               assertEquals("TRUNC", (new NumberEval(2d)).getNumberValue(), ((NumberEval)result).getNumberValue());
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestValue.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestValue.java
deleted file mode 100644 (file)
index 19a6d68..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * Tests for {@link Value}
- *
- * @author Josh Micich
- */
-public final class TestValue extends TestCase {
-
-       private static ValueEval invokeValue(String strText) {
-               ValueEval[] args = new ValueEval[] { new StringEval(strText), };
-               return new Value().evaluate(args, -1, (short) -1);
-       }
-
-       private static void confirmValue(String strText, double expected) {
-               ValueEval result = invokeValue(strText);
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(expected, ((NumberEval) result).getNumberValue(), 0.0);
-       }
-
-       private static void confirmValueError(String strText) {
-               ValueEval result = invokeValue(strText);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(ErrorEval.VALUE_INVALID, result);
-       }
-
-       public void testBasic() {
-
-               confirmValue("100", 100);
-               confirmValue("-2.3", -2.3);
-               confirmValue(".5", 0.5);
-               confirmValue(".5e2", 50);
-               confirmValue(".5e-2", 0.005);
-               confirmValue(".5e+2", 50);
-               confirmValue("+5", 5);
-               confirmValue("$1,000", 1000);
-               confirmValue("100.5e1", 1005);
-               confirmValue("1,0000", 10000);
-               confirmValue("1,000,0000", 10000000);
-               confirmValue("1,000,0000,00000", 1000000000000.0);
-               confirmValue(" 100 ", 100);
-               confirmValue(" + 100", 100);
-               confirmValue("10000", 10000);
-               confirmValue("$-5", -5);
-               confirmValue("$.5", 0.5);
-               confirmValue("123e+5", 12300000);
-               confirmValue("1,000e2", 100000);
-               confirmValue("$10e2", 1000);
-               confirmValue("$1,000e2", 100000);
-       }
-
-       public void testErrors() {
-               confirmValueError("1+1");
-               confirmValueError("1 1");
-               confirmValueError("1,00.0");
-               confirmValueError("1,00");
-               confirmValueError("$1,00.5e1");
-               confirmValueError("1,00.5e1");
-               confirmValueError("1,0,000");
-               confirmValueError("1,00,000");
-               confirmValueError("++100");
-               confirmValueError("$$5");
-               confirmValueError("-");
-               confirmValueError("+");
-               confirmValueError("$");
-               confirmValueError(",300");
-               confirmValueError("0.233,4");
-               confirmValueError("1e2.5");
-       }
-}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java
deleted file mode 100644 (file)
index 818409c..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.poi.hssf.record.formula.functions;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-/**
- * Tests for Excel functions SUMX2MY2(), SUMX2PY2(), SUMXMY2()
- *
- * @author Josh Micich
- */
-public final class TestXYNumericFunction extends TestCase {
-       private static final Function SUM_SQUARES = new Sumx2py2();
-       private static final Function DIFF_SQUARES = new Sumx2my2();
-       private static final Function SUM_SQUARES_OF_DIFFS = new Sumxmy2();
-
-       private static ValueEval invoke(Function function, ValueEval xArray, ValueEval yArray) {
-               ValueEval[] args = new ValueEval[] { xArray, yArray, };
-               return function.evaluate(args, -1, (short)-1);
-       }
-
-       private void confirm(Function function, ValueEval xArray, ValueEval yArray, double expected) {
-               ValueEval result = invoke(function, xArray, yArray);
-               assertEquals(NumberEval.class, result.getClass());
-               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
-       }
-       private void confirmError(Function function, ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
-               ValueEval result = invoke(function, xArray, yArray);
-               assertEquals(ErrorEval.class, result.getClass());
-               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
-       }
-
-       private void confirmError(ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
-               confirmError(SUM_SQUARES, xArray, yArray, expectedError);
-               confirmError(DIFF_SQUARES, xArray, yArray, expectedError);
-               confirmError(SUM_SQUARES_OF_DIFFS, xArray, yArray, expectedError);
-       }
-
-       public void testBasic() {
-               ValueEval[] xValues = {
-                       new NumberEval(1),
-                       new NumberEval(2),
-               };
-               ValueEval areaEvalX = createAreaEval(xValues);
-               confirm(SUM_SQUARES, areaEvalX, areaEvalX, 10.0);
-               confirm(DIFF_SQUARES, areaEvalX, areaEvalX, 0.0);
-               confirm(SUM_SQUARES_OF_DIFFS, areaEvalX, areaEvalX, 0.0);
-
-               ValueEval[] yValues = {
-                       new NumberEval(3),
-                       new NumberEval(4),
-               };
-               ValueEval areaEvalY = createAreaEval(yValues);
-               confirm(SUM_SQUARES, areaEvalX, areaEvalY, 30.0);
-               confirm(DIFF_SQUARES, areaEvalX, areaEvalY, -20.0);
-               confirm(SUM_SQUARES_OF_DIFFS, areaEvalX, areaEvalY, 8.0);
-       }
-
-       /**
-        * number of items in array is not limited to 30
-        */
-       public void testLargeArrays() {
-               ValueEval[] xValues = createMockNumberArray(100, 3);
-               ValueEval[] yValues = createMockNumberArray(100, 2);
-
-               confirm(SUM_SQUARES, createAreaEval(xValues), createAreaEval(yValues), 1300.0);
-               confirm(DIFF_SQUARES, createAreaEval(xValues), createAreaEval(yValues), 500.0);
-               confirm(SUM_SQUARES_OF_DIFFS, createAreaEval(xValues), createAreaEval(yValues), 100.0);
-       }
-
-
-       private ValueEval[] createMockNumberArray(int size, double value) {
-               ValueEval[] result = new ValueEval[size];
-               for (int i = 0; i < result.length; i++) {
-                       result[i] = new NumberEval(value);
-               }
-               return result;
-       }
-
-       private static ValueEval createAreaEval(ValueEval[] values) {
-               String refStr = "A1:A" + values.length;
-               return EvalFactory.createAreaEval(refStr, values);
-       }
-
-       public void testErrors() {
-               ValueEval[] xValues = {
-                               ErrorEval.REF_INVALID,
-                               new NumberEval(2),
-               };
-               ValueEval areaEvalX = createAreaEval(xValues);
-               ValueEval[] yValues = {
-                               new NumberEval(2),
-                               ErrorEval.NULL_INTERSECTION,
-               };
-               ValueEval areaEvalY = createAreaEval(yValues);
-               ValueEval[] zValues = { // wrong size
-                               new NumberEval(2),
-               };
-               ValueEval areaEvalZ = createAreaEval(zValues);
-
-               // if either arg is an error, that error propagates
-               confirmError(ErrorEval.REF_INVALID, ErrorEval.NAME_INVALID, ErrorEval.REF_INVALID);
-               confirmError(areaEvalX, ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
-               confirmError(ErrorEval.NAME_INVALID, areaEvalX, ErrorEval.NAME_INVALID);
-
-               // array sizes must match
-               confirmError(areaEvalX, areaEvalZ, ErrorEval.NA);
-               confirmError(areaEvalZ, areaEvalY, ErrorEval.NA);
-
-               // any error in an array item propagates up
-               confirmError(areaEvalX, areaEvalX, ErrorEval.REF_INVALID);
-
-               // search for errors array by array, not pair by pair
-               confirmError(areaEvalX, areaEvalY, ErrorEval.REF_INVALID);
-               confirmError(areaEvalY, areaEvalX, ErrorEval.NULL_INTERSECTION);
-       }
-}
index 811eef0913de00df87b46e98b242159366923a82..6de40073dce253d9a4723455276b16074421b6d3 100644 (file)
@@ -31,8 +31,8 @@ import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.formula.AreaPtg;
 import org.apache.poi.hssf.record.formula.FuncVarPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.ss.formula.EvaluationCell;
 import org.apache.poi.ss.formula.EvaluationListener;
 import org.apache.poi.ss.formula.WorkbookEvaluator;
index 2d97c1be059de7dcc98611ca647ad9e7b2e275e4..f28725669ce81955fa340b3d8bb68dfb245e7aa3 100644 (file)
 package org.apache.poi.hssf.usermodel;
 
 import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.record.NameRecord;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.ss.formula.EvaluationCell;
 import org.apache.poi.ss.formula.EvaluationListener;
 import org.apache.poi.ss.formula.WorkbookEvaluator;
index a9a259175b693ebbb3f9895c2b9f110b8650aa6d..128a767f5694410877102cd2f0cb00e1b3762bf9 100644 (file)
@@ -19,8 +19,8 @@ package org.apache.poi.ss.formula;
 
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 
 /**
  * Tests {@link org.apache.poi.ss.formula.CellCacheEntry}.
index c1d9523e73108292f247fb4d987a00c26809250e..87788ef8e410a27e8d656d2b3682ab2bb41ab0ce 100644 (file)
@@ -30,12 +30,12 @@ import junit.framework.TestCase;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
 import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.hssf.usermodel.FormulaExtractor;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFEvaluationTestHelper;
diff --git a/src/testcases/org/apache/poi/ss/formula/TestFormulaShifter.java b/src/testcases/org/apache/poi/ss/formula/TestFormulaShifter.java
new file mode 100644 (file)
index 0000000..9f840e1
--- /dev/null
@@ -0,0 +1,119 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula;
+
+import junit.framework.TestCase;
+import org.apache.poi.hssf.record.formula.AreaErrPtg;
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.ss.formula.FormulaShifter;
+
+/**
+ * Tests for {@link FormulaShifter}.
+ *
+ * @author Josh Micich
+ */
+public final class TestFormulaShifter extends TestCase {
+       // Note - the expected result row coordinates here were determined/verified
+       // in Excel 2007 by manually testing.
+
+       /**
+        * Tests what happens to area refs when a range of rows from inside, or overlapping are
+        * moved
+        */
+       public void testShiftAreasSourceRows() {
+
+               // all these operations are on an area ref spanning rows 10 to 20
+               AreaPtg aptg  = createAreaPtg(10, 20);
+
+               confirmAreaShift(aptg,  9, 21, 20, 30, 40);
+               confirmAreaShift(aptg, 10, 21, 20, 30, 40);
+               confirmAreaShift(aptg,  9, 20, 20, 30, 40);
+
+               confirmAreaShift(aptg, 8, 11,  -3, 7, 20); // simple expansion of top
+               // rows containing area top being shifted down:
+               confirmAreaShift(aptg, 8, 11,  3, 13, 20);
+               confirmAreaShift(aptg, 8, 11,  7, 17, 20);
+               confirmAreaShift(aptg, 8, 11,  8, 18, 20);
+               confirmAreaShift(aptg, 8, 11,  9, 12, 20); // note behaviour changes here
+               confirmAreaShift(aptg, 8, 11, 10, 12, 21);
+               confirmAreaShift(aptg, 8, 11, 12, 12, 23);
+               confirmAreaShift(aptg, 8, 11, 13, 10, 20);  // ignored
+
+               // rows from within being moved:
+               confirmAreaShift(aptg, 12, 16,  3, 10, 20);  // stay within - no change
+               confirmAreaShift(aptg, 11, 19, 20, 10, 20);  // move completely out - no change
+               confirmAreaShift(aptg, 16, 17, -6, 10, 20);  // moved exactly to top - no change
+               confirmAreaShift(aptg, 16, 17, -7, 11, 20);  // truncation at top
+               confirmAreaShift(aptg, 12, 16,  4, 10, 20);  // moved exactly to bottom - no change
+               confirmAreaShift(aptg, 12, 16,  6, 10, 17);  // truncation at bottom
+
+               // rows containing area bottom being shifted up:
+               confirmAreaShift(aptg, 18, 22, -1, 10, 19); // simple contraction at bottom
+               confirmAreaShift(aptg, 18, 22, -7, 10, 13); // simple contraction at bottom
+               confirmAreaShift(aptg, 18, 22, -8, 10, 17); // top calculated differently here
+               confirmAreaShift(aptg, 18, 22, -9,  9, 17);
+               confirmAreaShift(aptg, 18, 22,-15, 10, 20); // no change because range would be turned inside out
+               confirmAreaShift(aptg, 15, 19, -7, 13, 20); // dest truncates top (even though src is from inside range)
+               confirmAreaShift(aptg, 19, 23,-12,  7, 18); // complex: src encloses bottom, dest encloses top
+
+               confirmAreaShift(aptg, 18, 22,  5, 10, 25); // simple expansion at bottom
+       }
+       /**
+        * Tests what happens to an area ref when some outside rows are moved to overlap
+        * that area ref
+        */
+       public void testShiftAreasDestRows() {
+               // all these operations are on an area ref spanning rows 20 to 25
+               AreaPtg aptg  = createAreaPtg(20, 25);
+
+               // no change because no overlap:
+               confirmAreaShift(aptg,  5, 10,  9, 20, 25);
+               confirmAreaShift(aptg,  5, 10, 21, 20, 25);
+
+               confirmAreaShift(aptg, 11, 14, 10, 20, 25);
+
+               confirmAreaShift(aptg,   7, 17, 10, -1, -1); // converted to DeletedAreaRef
+               confirmAreaShift(aptg,   5, 15,  7, 23, 25); // truncation at top
+               confirmAreaShift(aptg,  13, 16, 10, 20, 22); // truncation at bottom
+       }
+
+       private static void confirmAreaShift(AreaPtg aptg,
+                       int firstRowMoved, int lastRowMoved, int numberRowsMoved,
+                       int expectedAreaFirstRow, int expectedAreaLastRow) {
+
+               FormulaShifter fs = FormulaShifter.createForRowShift(0, firstRowMoved, lastRowMoved, numberRowsMoved);
+               boolean expectedChanged = aptg.getFirstRow() != expectedAreaFirstRow || aptg.getLastRow() != expectedAreaLastRow;
+
+               AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
+               Ptg[] ptgs = { copyPtg, };
+               boolean actualChanged = fs.adjustFormula(ptgs, 0);
+               if (expectedAreaFirstRow < 0) {
+                       assertEquals(AreaErrPtg.class, ptgs[0].getClass());
+                       return;
+               }
+               assertEquals(expectedChanged, actualChanged);
+               assertEquals(copyPtg, ptgs[0]);  // expected to change in place (although this is not a strict requirement)
+               assertEquals(expectedAreaFirstRow, copyPtg.getFirstRow());
+               assertEquals(expectedAreaLastRow, copyPtg.getLastRow());
+
+       }
+       private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow) {
+               return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, false, false, false, false);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java b/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java
new file mode 100644 (file)
index 0000000..69b0c9b
--- /dev/null
@@ -0,0 +1,108 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula;
+
+import junit.framework.TestCase;
+import org.apache.poi.ss.formula.SheetNameFormatter;
+
+/**
+ * Tests for {@link SheetNameFormatter}
+ * 
+ * @author Josh Micich
+ */
+public final class TestSheetNameFormatter extends TestCase {
+
+       private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding) {
+               assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
+       }
+
+       /**
+        * Tests main public method 'format' 
+        */
+       public void testFormat() {
+               
+               confirmFormat("abc", "abc");
+               confirmFormat("123", "'123'");
+               
+               confirmFormat("my sheet", "'my sheet'"); // space
+               confirmFormat("A:MEM", "'A:MEM'"); // colon
+
+               confirmFormat("O'Brian", "'O''Brian'"); // single quote gets doubled
+               
+               
+               confirmFormat("3rdTimeLucky", "'3rdTimeLucky'"); // digit in first pos
+               confirmFormat("_", "_"); // plain underscore OK
+               confirmFormat("my_3rd_sheet", "my_3rd_sheet"); // underscores and digits OK
+               confirmFormat("A12220", "'A12220'"); 
+               confirmFormat("TAXRETURN19980415", "TAXRETURN19980415"); 
+       }
+       
+       public void testBooleanLiterals() {
+               confirmFormat("TRUE", "'TRUE'");
+               confirmFormat("FALSE", "'FALSE'");
+               confirmFormat("True", "'True'");
+               confirmFormat("fAlse", "'fAlse'");
+               
+               confirmFormat("Yes", "Yes");
+               confirmFormat("No", "No");
+       }
+       
+       private static void confirmCellNameMatch(String rawSheetName, boolean expected) {
+               assertEquals(expected, SheetNameFormatter.nameLooksLikePlainCellReference(rawSheetName));
+       }
+       
+       /**
+        * Tests functionality to determine whether a sheet name containing only letters and digits
+        * would look (to Excel) like a cell name.
+        */
+       public void testLooksLikePlainCellReference() {
+               
+               confirmCellNameMatch("A1", true);
+               confirmCellNameMatch("a111", true);
+               confirmCellNameMatch("AA", false);
+               confirmCellNameMatch("aa1", true);
+               confirmCellNameMatch("A1A", false);
+               confirmCellNameMatch("A1A1", false);
+               confirmCellNameMatch("Sh3", false);
+               confirmCellNameMatch("SALES20080101", false); // out of range
+       }
+       
+       private static void confirmCellRange(String text, int numberOfPrefixLetters, boolean expected) {
+               String prefix = text.substring(0, numberOfPrefixLetters);
+               String suffix = text.substring(numberOfPrefixLetters);
+               assertEquals(expected, SheetNameFormatter.cellReferenceIsWithinRange(prefix, suffix));
+       }
+       
+       /**
+        * Tests exact boundaries for names that look very close to cell names (i.e. contain 1 or more
+        * letters followed by one or more digits).
+        */
+       public void testCellRange() {
+               confirmCellRange("A1", 1, true);
+               confirmCellRange("a111", 1, true);
+               confirmCellRange("A65536", 1, true);
+               confirmCellRange("A65537", 1, false);
+               confirmCellRange("iv1", 2, true);
+               confirmCellRange("IW1", 2, false);
+               confirmCellRange("AAA1", 3, false);
+               confirmCellRange("a111", 1, true);
+               confirmCellRange("Sheet1", 6, false);
+               confirmCellRange("iV65536", 2, true);  // max cell in Excel 97-2003
+               confirmCellRange("IW65537", 2, false);
+       }
+}
index 5e59933cf6683a4228e5de581e42483c0e3ea62c..8dac906ecb30a686735aaf6dfd49aa7d54e908f7 100644 (file)
@@ -28,11 +28,11 @@ import org.apache.poi.hssf.record.formula.DeletedRef3DPtg;
 import org.apache.poi.hssf.record.formula.IntPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.RefErrorPtg;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.MissingArgEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.MissingArgEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
 import org.apache.poi.hssf.usermodel.HSSFRow;
diff --git a/src/testcases/org/apache/poi/ss/formula/atp/TestRandBetween.java b/src/testcases/org/apache/poi/ss/formula/atp/TestRandBetween.java
new file mode 100644 (file)
index 0000000..6b8d503
--- /dev/null
@@ -0,0 +1,193 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.atp;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Testcase for 'Analysis Toolpak' function RANDBETWEEN()
+ * 
+ * @author Brendan Nolan
+ */
+public class TestRandBetween extends TestCase {
+
+       private Workbook wb;
+       private FormulaEvaluator evaluator;
+       private Cell bottomValueCell;
+       private Cell topValueCell;
+       private Cell formulaCell;
+       
+       @Override
+       protected void setUp() throws Exception {
+               super.setUp();
+               wb = HSSFTestDataSamples.openSampleWorkbook("TestRandBetween.xls");
+               evaluator = wb.getCreationHelper().createFormulaEvaluator();
+               
+               Sheet sheet = wb.createSheet("RandBetweenSheet");
+               Row row = sheet.createRow(0);
+               bottomValueCell = row.createCell(0);
+               topValueCell = row.createCell(1);
+               formulaCell = row.createCell(2, Cell.CELL_TYPE_FORMULA);
+       }
+       
+       @Override
+       protected void tearDown() throws Exception {
+               // TODO Auto-generated method stub
+               super.tearDown();
+       }
+       
+       /**
+        * Check where values are the same
+        */
+       public void testRandBetweenSameValues() {
+               
+               evaluator.clearAllCachedResultValues();
+               formulaCell.setCellFormula("RANDBETWEEN(1,1)");
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(1, formulaCell.getNumericCellValue(), 0);
+               evaluator.clearAllCachedResultValues();
+               formulaCell.setCellFormula("RANDBETWEEN(-1,-1)");
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
+
+       }
+       
+       /**
+        * Check special case where rounded up bottom value is greater than 
+        * top value.
+        */
+       public void testRandBetweenSpecialCase() {
+               
+
+               bottomValueCell.setCellValue(0.05);             
+               topValueCell.setCellValue(0.1);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(1, formulaCell.getNumericCellValue(), 0);
+               bottomValueCell.setCellValue(-0.1);             
+               topValueCell.setCellValue(-0.05);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(0, formulaCell.getNumericCellValue(), 0);
+               bottomValueCell.setCellValue(-1.1);             
+               topValueCell.setCellValue(-1.05);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
+               bottomValueCell.setCellValue(-1.1);             
+               topValueCell.setCellValue(-1.1);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(-1, formulaCell.getNumericCellValue(), 0);
+       }
+       
+       /**
+        * Check top value of BLANK which Excel will evaluate as 0
+        */
+       public void testRandBetweenTopBlank() {
+
+               bottomValueCell.setCellValue(-1);               
+               topValueCell.setCellType(Cell.CELL_TYPE_BLANK);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertTrue(formulaCell.getNumericCellValue() == 0 || formulaCell.getNumericCellValue() == -1);
+       
+       }
+       /**
+        * Check where input values are of wrong type
+        */
+       public void testRandBetweenWrongInputTypes() {
+               // Check case where bottom input is of the wrong type
+               bottomValueCell.setCellValue("STRING");         
+               topValueCell.setCellValue(1);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
+               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
+               
+               
+               // Check case where top input is of the wrong type
+               bottomValueCell.setCellValue(1);
+               topValueCell.setCellValue("STRING");            
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
+               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
+
+               // Check case where both inputs are of wrong type
+               bottomValueCell.setCellValue("STRING");
+               topValueCell.setCellValue("STRING");            
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
+               assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), formulaCell.getErrorCellValue());
+       
+       }
+       
+       /**
+        * Check case where bottom is greater than top
+        */
+       public void testRandBetweenBottomGreaterThanTop() {
+
+               // Check case where bottom is greater than top
+               bottomValueCell.setCellValue(1);                
+               topValueCell.setCellValue(0);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
+               assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), formulaCell.getErrorCellValue());              
+               bottomValueCell.setCellValue(1);                
+               topValueCell.setCellType(Cell.CELL_TYPE_BLANK);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertEquals(Cell.CELL_TYPE_ERROR, formulaCell.getCachedFormulaResultType());
+               assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), formulaCell.getErrorCellValue());
+       }
+       
+       /**
+        * Boundary check of Double MIN and MAX values
+        */
+       public void testRandBetweenBoundaryCheck() {
+
+               bottomValueCell.setCellValue(Double.MIN_VALUE);         
+               topValueCell.setCellValue(Double.MAX_VALUE);
+               formulaCell.setCellFormula("RANDBETWEEN($A$1,$B$1)");
+               evaluator.clearAllCachedResultValues();
+               evaluator.evaluateFormulaCell(formulaCell);
+               assertTrue(formulaCell.getNumericCellValue() >= Double.MIN_VALUE && formulaCell.getNumericCellValue() <= Double.MAX_VALUE);             
+               
+       }
+       
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculator.java b/src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculator.java
new file mode 100644 (file)
index 0000000..22d3ba3
--- /dev/null
@@ -0,0 +1,67 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.atp;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.usermodel.DateUtil;
+
+/**
+ * Specific test cases for YearFracCalculator
+ */
+public final class TestYearFracCalculator extends TestCase {
+
+       public void testBasis1() {
+               confirm(md(1999, 1, 1), md(1999, 4, 5), 1, 0.257534247);
+               confirm(md(1999, 4, 1), md(1999, 4, 5), 1, 0.010958904);
+               confirm(md(1999, 4, 1), md(1999, 4, 4), 1, 0.008219178);
+               confirm(md(1999, 4, 2), md(1999, 4, 5), 1, 0.008219178);
+               confirm(md(1999, 3, 31), md(1999, 4, 3), 1, 0.008219178);
+               confirm(md(1999, 4, 5), md(1999, 4, 8), 1, 0.008219178);
+               confirm(md(1999, 4, 4), md(1999, 4, 7), 1, 0.008219178);
+               confirm(md(2000, 2, 5), md(2000, 6, 1), 0, 0.322222222);
+       }
+
+       private void confirm(double startDate, double endDate, int basis, double expectedValue) {
+               double actualValue;
+               try {
+                       actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
+               } catch (EvaluationException e) {
+                       throw new RuntimeException(e);
+               }
+               double diff = actualValue - expectedValue;
+               if (Math.abs(diff) >  0.000000001) {
+                       double hours = diff * 365 * 24;
+                       System.out.println(startDate + " " + endDate + " off by " + hours + " hours");
+                       assertEquals(expectedValue, actualValue, 0.000000001);
+               }
+               
+       }
+
+       private static double md(int year, int month, int day) {
+               Calendar c = new GregorianCalendar();
+               
+               c.set(year, month-1, day, 0, 0, 0);
+               c.set(Calendar.MILLISECOND, 0);
+               return DateUtil.getExcelDate(c.getTime());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculatorFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculatorFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..d735fe8
--- /dev/null
@@ -0,0 +1,178 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.atp;
+
+import java.io.PrintStream;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.ComparisonFailure;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Tests YearFracCalculator using test-cases listed in a sample spreadsheet
+ * 
+ * @author Josh Micich
+ */
+public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
+       
+       private static final class SS {
+
+               public static final int BASIS_COLUMN = 1; // "B"
+               public static final int START_YEAR_COLUMN = 2; // "C"
+               public static final int END_YEAR_COLUMN = 5; // "F"
+               public static final int YEARFRAC_FORMULA_COLUMN = 11; // "L"
+               public static final int EXPECTED_RESULT_COLUMN = 13; // "N"
+       }
+
+       public void testAll() {
+               
+               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls");
+               HSSFSheet sheet = wb.getSheetAt(0);
+               HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb);
+               int nSuccess = 0;
+               int nFailures = 0;
+               int nUnexpectedErrors = 0;
+               Iterator rowIterator = sheet.rowIterator();
+               while(rowIterator.hasNext()) {
+                       HSSFRow row = (HSSFRow) rowIterator.next();
+                       
+                       HSSFCell cell = row.getCell(SS.YEARFRAC_FORMULA_COLUMN);
+                       if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
+                               continue;
+                       }
+                       try {
+                               processRow(row, cell, formulaEvaluator);
+                               nSuccess++;
+                       } catch (RuntimeException e) {
+                               nUnexpectedErrors ++;
+                               printShortStackTrace(System.err, e);
+                       } catch (AssertionFailedError e) {
+                               nFailures ++;
+                               printShortStackTrace(System.err, e);
+                       }
+               }
+               if (nUnexpectedErrors + nFailures > 0) {
+                       String msg = nFailures + " failures(s) and " + nUnexpectedErrors 
+                               + " unexpected errors(s) occurred. See stderr for details";
+                       throw new AssertionFailedError(msg);
+               }
+               if (nSuccess < 1) {
+                       throw new RuntimeException("No test sample cases found");
+               }
+       }
+       
+       private static void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator) {
+               
+               double startDate = makeDate(row, SS.START_YEAR_COLUMN);
+               double endDate = makeDate(row, SS.END_YEAR_COLUMN);
+               
+               int basis = getIntCell(row, SS.BASIS_COLUMN);
+               
+               double expectedValue = getDoubleCell(row, SS.EXPECTED_RESULT_COLUMN);
+               
+               double actualValue;
+               try {
+                       actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
+               } catch (EvaluationException e) {
+                       throw new RuntimeException(e);
+               }
+               if (expectedValue != actualValue) {
+                       throw new ComparisonFailure("Direct calculate failed - row " + (row.getRowNum()+1), 
+                                       String.valueOf(expectedValue), String.valueOf(actualValue));
+               }
+               actualValue = formulaEvaluator.evaluate(cell).getNumberValue();
+               if (expectedValue != actualValue) {
+                       throw new ComparisonFailure("Formula evaluate failed - row " + (row.getRowNum()+1), 
+                                       String.valueOf(expectedValue), String.valueOf(actualValue));
+               }
+       }
+
+       private static double makeDate(HSSFRow row, int yearColumn) {
+               int year = getIntCell(row, yearColumn + 0);
+               int month = getIntCell(row, yearColumn + 1);
+               int day = getIntCell(row, yearColumn + 2);
+               Calendar c = new GregorianCalendar(year, month-1, day, 0, 0, 0);
+               c.set(Calendar.MILLISECOND, 0);
+               return HSSFDateUtil.getExcelDate(c.getTime());
+       }
+
+       private static int getIntCell(HSSFRow row, int colIx) {
+               double dVal = getDoubleCell(row, colIx);
+               if (Math.floor(dVal) != dVal) {
+                       throw new RuntimeException("Non integer value (" + dVal 
+                                       + ") cell found at column " + (char)('A' + colIx));
+               }
+               return (int)dVal;
+       }
+
+       private static double getDoubleCell(HSSFRow row, int colIx) {
+               HSSFCell cell = row.getCell(colIx);
+               if (cell == null) {
+                       throw new RuntimeException("No cell found at column " + colIx);
+               }
+               double dVal = cell.getNumericCellValue();
+               return dVal;
+       }
+
+       /**
+        * Useful to keep output concise when expecting many failures to be reported by this test case
+        * TODO - refactor duplicates in other Test~FromSpreadsheet classes
+        */
+       private static void printShortStackTrace(PrintStream ps, Throwable e) {
+               StackTraceElement[] stes = e.getStackTrace();
+               
+               int startIx = 0;
+               // skip any top frames inside junit.framework.Assert
+               while(startIx<stes.length) {
+                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
+                               break;
+                       }
+                       startIx++;
+               }
+               // skip bottom frames (part of junit framework)
+               int endIx = startIx+1;
+               while(endIx < stes.length) {
+                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
+                               break;
+                       }
+                       endIx++;
+               }
+               if(startIx >= endIx) {
+                       // something went wrong. just print the whole stack trace
+                       e.printStackTrace(ps);
+               }
+               endIx -= 4; // skip 4 frames of reflection invocation
+               ps.println(e.toString());
+               for(int i=startIx; i<endIx; i++) {
+                       ps.println("\tat " + stes[i].toString());
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/AllFormulaEvalTests.java b/src/testcases/org/apache/poi/ss/formula/eval/AllFormulaEvalTests.java
new file mode 100644 (file)
index 0000000..80f1a1a
--- /dev/null
@@ -0,0 +1,46 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Collects all tests the package <tt>org.apache.poi.hssf.record.formula.eval</tt>.
+ *
+ * @author Josh Micich
+ */
+public class AllFormulaEvalTests {
+
+       public static Test suite() {
+               TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
+               result.addTestSuite(TestAreaEval.class);
+               result.addTestSuite(TestCircularReferences.class);
+               result.addTestSuite(TestDivideEval.class);
+               result.addTestSuite(TestEqualEval.class);
+               result.addTestSuite(TestExternalFunction.class);
+               result.addTestSuite(TestFormulaBugs.class);
+               result.addTestSuite(TestFormulasFromSpreadsheet.class);
+               result.addTestSuite(TestMinusZeroResult.class);
+               result.addTestSuite(TestMissingArgEval.class);
+               result.addTestSuite(TestPercentEval.class);
+               result.addTestSuite(TestRangeEval.class);
+               result.addTestSuite(TestUnaryPlusEval.class);
+               return result;
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/EvalInstances.java b/src/testcases/org/apache/poi/ss/formula/eval/EvalInstances.java
new file mode 100644 (file)
index 0000000..4a15444
--- /dev/null
@@ -0,0 +1,53 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import org.apache.poi.ss.formula.functions.Function;
+
+/**
+ * Collects eval instances for easy access by tests in this package
+ *
+ * @author Josh Micich
+ */
+final class EvalInstances {
+       private EvalInstances() {
+               // no instances of this class
+       }
+
+       public static final Function Add = TwoOperandNumericOperation.AddEval;
+       public static final Function Subtract = TwoOperandNumericOperation.SubtractEval;
+       public static final Function Multiply = TwoOperandNumericOperation.MultiplyEval;
+       public static final Function Divide = TwoOperandNumericOperation.DivideEval;
+
+       public static final Function Power = TwoOperandNumericOperation.PowerEval;
+
+       public static final Function Percent = PercentEval.instance;
+
+       public static final Function UnaryMinus = UnaryMinusEval.instance;
+       public static final Function UnaryPlus = UnaryPlusEval.instance;
+
+       public static final Function Equal = RelationalOperationEval.EqualEval;
+       public static final Function LessThan = RelationalOperationEval.LessThanEval;
+       public static final Function LessEqual = RelationalOperationEval.LessEqualEval;
+       public static final Function GreaterThan = RelationalOperationEval.GreaterThanEval;
+       public static final Function GreaterEqual = RelationalOperationEval.GreaterEqualEval;
+       public static final Function NotEqual = RelationalOperationEval.NotEqualEval;
+
+       public static final Function Range = RangeEval.instance;
+       public static final Function Concat = ConcatEval.instance;
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestAreaEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestAreaEval.java
new file mode 100644 (file)
index 0000000..3965766
--- /dev/null
@@ -0,0 +1,62 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.ss.formula.functions.EvalFactory;
+
+/**
+ * Tests for <tt>AreaEval</tt>
+ *
+ * @author Josh Micich
+ */
+public final class TestAreaEval extends TestCase {
+
+       public void testGetValue_bug44950() {
+               // TODO - this test probably isn't testing much anymore
+               AreaPtg ptg = new AreaPtg("B2:D3");
+               NumberEval one = new NumberEval(1);
+               ValueEval[] values = {
+                               one,
+                               new NumberEval(2),
+                               new NumberEval(3),
+                               new NumberEval(4),
+                               new NumberEval(5),
+                               new NumberEval(6),
+               };
+               AreaEval ae = EvalFactory.createAreaEval(ptg, values);
+               if (one == ae.getAbsoluteValue(1, 2)) {
+                       throw new AssertionFailedError("Identified bug 44950 a");
+               }
+               confirm(1, ae, 1, 1);
+               confirm(2, ae, 1, 2);
+               confirm(3, ae, 1, 3);
+               confirm(4, ae, 2, 1);
+               confirm(5, ae, 2, 2);
+               confirm(6, ae, 2, 3);
+
+       }
+
+       private static void confirm(int expectedValue, AreaEval ae, int row, int col) {
+               NumberEval v = (NumberEval) ae.getAbsoluteValue(row, col);
+               assertEquals(expectedValue, v.getNumberValue(), 0.0);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestCircularReferences.java b/src/testcases/org/apache/poi/ss/formula/eval/TestCircularReferences.java
new file mode 100644 (file)
index 0000000..ca3b7b5
--- /dev/null
@@ -0,0 +1,169 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+/**
+ * Tests HSSFFormulaEvaluator for its handling of cell formula circular references.
+ *
+ * @author Josh Micich
+ */
+public final class TestCircularReferences extends TestCase {
+       /**
+        * Translates StackOverflowError into AssertionFailedError
+        */
+       private static CellValue evaluateWithCycles(HSSFWorkbook wb, HSSFCell testCell)
+                       throws AssertionFailedError {
+               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
+               try {
+                       return evaluator.evaluate(testCell);
+               } catch (StackOverflowError e) {
+                       throw new AssertionFailedError( "circular reference caused stack overflow error");
+               }
+       }
+       /**
+        * Makes sure that the specified evaluated cell value represents a circular reference error.
+        */
+       private static void confirmCycleErrorCode(CellValue cellValue) {
+               assertTrue(cellValue.getCellType() == HSSFCell.CELL_TYPE_ERROR);
+               assertEquals(ErrorEval.CIRCULAR_REF_ERROR.getErrorCode(), cellValue.getErrorValue());
+       }
+
+
+       /**
+        * ASF Bugzilla Bug 44413
+        * "INDEX() formula cannot contain its own location in the data array range"
+        */
+       public void testIndexFormula() {
+
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+
+               int colB = 1;
+               sheet.createRow(0).createCell(colB).setCellValue(1);
+               sheet.createRow(1).createCell(colB).setCellValue(2);
+               sheet.createRow(2).createCell(colB).setCellValue(3);
+               HSSFRow row4 = sheet.createRow(3);
+               HSSFCell testCell = row4.createCell(0);
+               // This formula should evaluate to the contents of B2,
+               testCell.setCellFormula("INDEX(A1:B4,2,2)");
+               // However the range A1:B4 also includes the current cell A4.  If the other parameters
+               // were 4 and 1, this would represent a circular reference.  Prior to v3.2 POI would
+               // 'fully' evaluate ref arguments before invoking operators, which raised the possibility of
+               // cycles / StackOverflowErrors.
+
+
+               CellValue cellValue = evaluateWithCycles(wb, testCell);
+
+               assertTrue(cellValue.getCellType() == HSSFCell.CELL_TYPE_NUMERIC);
+               assertEquals(2, cellValue.getNumberValue(), 0);
+       }
+
+       /**
+        * Cell A1 has formula "=A1"
+        */
+       public void testSimpleCircularReference() {
+
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+
+               HSSFRow row = sheet.createRow(0);
+               HSSFCell testCell = row.createCell(0);
+               testCell.setCellFormula("A1");
+
+               CellValue cellValue = evaluateWithCycles(wb, testCell);
+
+               confirmCycleErrorCode(cellValue);
+       }
+
+       /**
+        * A1=B1, B1=C1, C1=D1, D1=A1
+        */
+       public void testMultiLevelCircularReference() {
+
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+
+               HSSFRow row = sheet.createRow(0);
+               row.createCell(0).setCellFormula("B1");
+               row.createCell(1).setCellFormula("C1");
+               row.createCell(2).setCellFormula("D1");
+               HSSFCell testCell = row.createCell(3);
+               testCell.setCellFormula("A1");
+
+               CellValue cellValue = evaluateWithCycles(wb, testCell);
+
+               confirmCycleErrorCode(cellValue);
+       }
+
+       public void testIntermediateCircularReferenceResults_bug46898() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+
+               HSSFRow row = sheet.createRow(0);
+
+               HSSFCell cellA1 = row.createCell(0);
+               HSSFCell cellB1 = row.createCell(1);
+               HSSFCell cellC1 = row.createCell(2);
+               HSSFCell cellD1 = row.createCell(3);
+               HSSFCell cellE1 = row.createCell(4);
+
+               cellA1.setCellFormula("IF(FALSE, 1+B1, 42)");
+               cellB1.setCellFormula("1+C1");
+               cellC1.setCellFormula("1+D1");
+               cellD1.setCellFormula("1+E1");
+               cellE1.setCellFormula("1+A1");
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv;
+
+               // Happy day flow - evaluate A1 first
+               cv = fe.evaluate(cellA1);
+               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(42.0, cv.getNumberValue(), 0.0);
+               cv = fe.evaluate(cellB1); // no circ-ref-error because A1 result is cached
+               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(46.0, cv.getNumberValue(), 0.0);
+
+               // Show the bug - evaluate another cell from the loop first
+               fe.clearAllCachedResultValues();
+               cv = fe.evaluate(cellB1);
+               if (cv.getCellType() == ErrorEval.CIRCULAR_REF_ERROR.getErrorCode()) {
+                       throw new AssertionFailedError("Identified bug 46898");
+               }
+               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(46.0, cv.getNumberValue(), 0.0);
+
+               // start evaluation on another cell
+               fe.clearAllCachedResultValues();
+               cv = fe.evaluate(cellE1);
+               assertEquals(Cell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(43.0, cv.getNumberValue(), 0.0);
+
+
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestDivideEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestDivideEval.java
new file mode 100644 (file)
index 0000000..11c661d
--- /dev/null
@@ -0,0 +1,62 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.functions.EvalFactory;
+import org.apache.poi.ss.formula.functions.NumericFunctionInvoker;
+
+/**
+ * Test for divide operator evaluator.
+ *
+ * @author Josh Micich
+ */
+public final class TestDivideEval extends TestCase {
+
+       private static void confirm(ValueEval arg0, ValueEval arg1, double expectedResult) {
+               ValueEval[] args = {
+                       arg0, arg1,
+               };
+
+               double result = NumericFunctionInvoker.invoke(EvalInstances.Divide, args, 0, 0);
+
+               assertEquals(expectedResult, result, 0);
+       }
+
+       public void testBasic() {
+               confirm(new NumberEval(5), new NumberEval(2), 2.5);
+               confirm(new NumberEval(3), new NumberEval(16), 0.1875);
+               confirm(new NumberEval(-150), new NumberEval(-15), 10.0);
+               confirm(new StringEval("0.2"), new NumberEval(0.05), 4.0);
+               confirm(BoolEval.TRUE, new StringEval("-0.2"), -5.0);
+       }
+
+       public void test1x1Area() {
+               AreaEval ae0 = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
+               AreaEval ae1 = EvalFactory.createAreaEval("C2:C2", new ValueEval[] { new NumberEval(10), });
+               confirm(ae0, ae1, 5);
+       }
+       public void testDivZero() {
+               ValueEval[] args = {
+                       new NumberEval(5), NumberEval.ZERO,
+               };
+               ValueEval result = EvalInstances.Divide.evaluate(args, 0, (short) 0);
+               assertEquals(ErrorEval.DIV_ZERO, result);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestEqualEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestEqualEval.java
new file mode 100644 (file)
index 0000000..7eaa3e9
--- /dev/null
@@ -0,0 +1,169 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.functions.EvalFactory;
+import org.apache.poi.ss.formula.functions.Function;
+
+/**
+ * Test for {@link EqualEval}
+ *
+ * @author Josh Micich
+ */
+public final class TestEqualEval extends TestCase {
+       // convenient access to namepace
+       private static final EvalInstances EI = null;
+
+       /**
+        * Test for bug observable at svn revision 692218 (Sep 2008)<br/>
+        * The value from a 1x1 area should be taken immediately, regardless of srcRow and srcCol
+        */
+       public void test1x1AreaOperand() {
+
+               ValueEval[] values = { BoolEval.FALSE, };
+               ValueEval[] args = {
+                       EvalFactory.createAreaEval("B1:B1", values),
+                       BoolEval.FALSE,
+               };
+               ValueEval result = evaluate(EI.Equal, args, 10, 10);
+               if (result instanceof ErrorEval) {
+                       if (result == ErrorEval.VALUE_INVALID) {
+                               throw new AssertionFailedError("Identified bug in evaluation of 1x1 area");
+                       }
+               }
+               assertEquals(BoolEval.class, result.getClass());
+               assertTrue(((BoolEval)result).getBooleanValue());
+       }
+       /**
+        * Empty string is equal to blank
+        */
+       public void testBlankEqualToEmptyString() {
+
+               ValueEval[] args = {
+                       new StringEval(""),
+                       BlankEval.instance,
+               };
+               ValueEval result = evaluate(EI.Equal, args, 10, 10);
+               assertEquals(BoolEval.class, result.getClass());
+               BoolEval be = (BoolEval) result;
+               if (!be.getBooleanValue()) {
+                       throw new AssertionFailedError("Identified bug blank/empty string equality");
+               }
+               assertTrue(be.getBooleanValue());
+       }
+
+       /**
+        * Test for bug 46613 (observable at svn r737248)
+        */
+       public void testStringInsensitive_bug46613() {
+               if (!evalStringCmp("abc", "aBc", EI.Equal)) {
+                       throw new AssertionFailedError("Identified bug 46613");
+               }
+               assertTrue(evalStringCmp("abc", "aBc", EI.Equal));
+               assertTrue(evalStringCmp("ABC", "azz", EI.LessThan));
+               assertTrue(evalStringCmp("abc", "AZZ", EI.LessThan));
+               assertTrue(evalStringCmp("ABC", "aaa", EI.GreaterThan));
+               assertTrue(evalStringCmp("abc", "AAA", EI.GreaterThan));
+       }
+
+       private static boolean evalStringCmp(String a, String b, Function cmpOp) {
+               ValueEval[] args = {
+                       new StringEval(a),
+                       new StringEval(b),
+               };
+               ValueEval result = evaluate(cmpOp, args, 10, 20);
+               assertEquals(BoolEval.class, result.getClass());
+               BoolEval be = (BoolEval) result;
+               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
+        * but because "-A1" evaluated to +0.0
+        * <p/>
+        * Note - the original diagnosis of bug 47198 was that
+        * "Excel considers -0.0 to be equal to 0.0" which is NQR
+        * See {@link TestMinusZeroResult} for more specific tests regarding -0.0.
+        */
+       public void testZeroEquality_bug47198() {
+               NumberEval zero = new NumberEval(0.0);
+               NumberEval mZero = (NumberEval) evaluate(UnaryMinusEval.instance, new ValueEval[] { zero, }, 0, 0);
+               if (Double.doubleToLongBits(mZero.getNumberValue()) == 0x8000000000000000L) {
+                       throw new AssertionFailedError("Identified bug 47198: unary minus should convert -0.0 to 0.0");
+               }
+               ValueEval[] args = { zero, mZero, };
+               BoolEval result = (BoolEval) evaluate(EI.Equal, args, 0, 0);
+               if (!result.getBooleanValue()) {
+                       throw new AssertionFailedError("Identified bug 47198: -0.0 != 0.0");
+               }
+       }
+
+       public void testRounding_bug47598() {
+               double x = 1+1.0028-0.9973; // should be 1.0055, but has IEEE rounding
+               assertFalse(x == 1.0055);
+
+               NumberEval a = new NumberEval(x);
+               NumberEval b = new NumberEval(1.0055);
+               assertEquals("1.0055", b.getStringValue());
+
+               ValueEval[] args = { a, b, };
+               BoolEval result = (BoolEval) evaluate(EI.Equal, args, 0, 0);
+               if (!result.getBooleanValue()) {
+                       throw new AssertionFailedError("Identified bug 47598: 1+1.0028-0.9973 != 1.0055");
+               }
+       }
+
+       private static ValueEval evaluate(Function oper, ValueEval[] args, int srcRowIx, int srcColIx) {
+               return oper.evaluate(args, srcRowIx, (short) srcColIx);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestExternalFunction.java b/src/testcases/org/apache/poi/ss/formula/eval/TestExternalFunction.java
new file mode 100644 (file)
index 0000000..30500b1
--- /dev/null
@@ -0,0 +1,95 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
+import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+
+/**
+ * @author Josh Micich
+ * @author Petr Udalau - registering UDFs in workbook and using ToolPacks.
+ */
+public final class TestExternalFunction extends TestCase {
+
+       private static class MyFunc implements FreeRefFunction {
+               public MyFunc() {
+                       //
+               }
+
+               public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+                       if (args.length != 1 || !(args[0] instanceof StringEval)) {
+                               return ErrorEval.VALUE_INVALID;
+                       }
+                       StringEval input = (StringEval) args[0];
+                       return new StringEval(input.getStringValue() + "abc");
+               }
+       }
+
+       private static class MyFunc2 implements FreeRefFunction {
+               public MyFunc2() {
+                       //
+               }
+
+               public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+                       if (args.length != 1 || !(args[0] instanceof StringEval)) {
+                               return ErrorEval.VALUE_INVALID;
+                       }
+                       StringEval input = (StringEval) args[0];
+                       return new StringEval(input.getStringValue() + "abc2");
+               }
+       }
+
+       /**
+        * Checks that an external function can get invoked from the formula
+        * evaluator.
+        */
+       public void testInvoke() {
+               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
+               HSSFSheet sheet = wb.getSheetAt(0);
+
+               /**
+                * register the two test UDFs in a UDF finder, to be passed to the evaluator
+                */
+               UDFFinder udff1 = new DefaultUDFFinder(new String[] { "myFunc", },
+                               new FreeRefFunction[] { new MyFunc(), });
+               UDFFinder udff2 = new DefaultUDFFinder(new String[] { "myFunc2", },
+                               new FreeRefFunction[] { new MyFunc2(), });
+               UDFFinder udff = new AggregatingUDFFinder(udff1, udff2);
+
+
+               HSSFRow row = sheet.getRow(0);
+               HSSFCell myFuncCell = row.getCell(1); // =myFunc("_")
+
+               HSSFCell myFunc2Cell = row.getCell(2); // =myFunc2("_")
+
+               HSSFFormulaEvaluator fe = HSSFFormulaEvaluator.create(wb, null, udff);
+               assertEquals("_abc", fe.evaluate(myFuncCell).getStringValue());
+               assertEquals("_abc2", fe.evaluate(myFunc2Cell).getStringValue());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestFormulaBugs.java b/src/testcases/org/apache/poi/ss/formula/eval/TestFormulaBugs.java
new file mode 100644 (file)
index 0000000..824c8ab
--- /dev/null
@@ -0,0 +1,176 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Miscellaneous tests for bugzilla entries.<p/> The test name contains the
+ * bugzilla bug id.
+ * 
+ * 
+ * @author Josh Micich
+ */
+public final class TestFormulaBugs extends TestCase {
+
+       /**
+        * Bug 27349 - VLOOKUP with reference to another sheet.<p/> This test was
+        * added <em>long</em> after the relevant functionality was fixed.
+        */
+       public void test27349() {
+               // 27349-vlookupAcrossSheets.xls is bugzilla/attachment.cgi?id=10622
+               InputStream is = HSSFTestDataSamples.openSampleFileStream("27349-vlookupAcrossSheets.xls");
+               HSSFWorkbook wb;
+               try {
+                       // original bug may have thrown exception here, or output warning to
+                       // stderr
+                       wb = new HSSFWorkbook(is);
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+
+               HSSFSheet sheet = wb.getSheetAt(0);
+               HSSFRow row = sheet.getRow(1);
+               HSSFCell cell = row.getCell(0);
+
+               // this definitely would have failed due to 27349
+               assertEquals("VLOOKUP(1,'DATA TABLE'!$A$8:'DATA TABLE'!$B$10,2)", cell
+                               .getCellFormula());
+
+               // We might as well evaluate the formula
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv = fe.evaluate(cell);
+
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(3.0, cv.getNumberValue(), 0.0);
+       }
+
+       /**
+        * Bug 27405 - isnumber() formula always evaluates to false in if statement<p/>
+        * 
+        * seems to be a duplicate of 24925
+        */
+       public void test27405() {
+
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("input");
+               // input row 0
+               HSSFRow row = sheet.createRow(0);
+               HSSFCell cell = row.createCell(0);
+               cell = row.createCell(1);
+               cell.setCellValue(1); // B1
+               // input row 1
+               row = sheet.createRow(1);
+               cell = row.createCell(1);
+               cell.setCellValue(999); // B2
+
+               int rno = 4;
+               row = sheet.createRow(rno);
+               cell = row.createCell(1); // B5
+               cell.setCellFormula("isnumber(b1)");
+               cell = row.createCell(3); // D5
+               cell.setCellFormula("IF(ISNUMBER(b1),b1,b2)");
+
+               if (false) { // set true to check excel file manually
+                       // bug report mentions 'Editing the formula in excel "fixes" the problem.'
+                       try {
+                               FileOutputStream fileOut = new FileOutputStream("27405output.xls");
+                               wb.write(fileOut);
+                               fileOut.close();
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
+               
+               // use POI's evaluator as an extra sanity check
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv;
+               cv = fe.evaluate(cell);
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(1.0, cv.getNumberValue(), 0.0);
+               
+               cv = fe.evaluate(row.getCell(1));
+               assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, cv.getCellType());
+               assertEquals(true, cv.getBooleanValue());
+       }
+
+       /**
+        * Bug 42448 - Can't parse SUMPRODUCT(A!C7:A!C67, B8:B68) / B69 <p/>
+        */
+       public void test42448() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet1 = wb.createSheet("Sheet1");
+
+               HSSFRow row = sheet1.createRow(0);
+               HSSFCell cell = row.createCell(0);
+
+               // it's important to create the referenced sheet first
+               HSSFSheet sheet2 = wb.createSheet("A"); // note name 'A'
+               // TODO - POI crashes if the formula is added before this sheet
+               // RuntimeException("Zero length string is an invalid sheet name")
+               // Excel doesn't crash but the formula doesn't work until it is
+               // re-entered
+
+               String inputFormula = "SUMPRODUCT(A!C7:A!C67, B8:B68) / B69"; // as per bug report
+               try {
+                       cell.setCellFormula(inputFormula); 
+               } catch (StringIndexOutOfBoundsException e) {
+                       throw new AssertionFailedError("Identified bug 42448");
+               }
+
+               assertEquals("SUMPRODUCT(A!C7:A!C67,B8:B68)/B69", cell.getCellFormula());
+
+               // might as well evaluate the sucker...
+
+               addCell(sheet2, 5, 2, 3.0); // A!C6
+               addCell(sheet2, 6, 2, 4.0); // A!C7
+               addCell(sheet2, 66, 2, 5.0); // A!C67
+               addCell(sheet2, 67, 2, 6.0); // A!C68
+
+               addCell(sheet1, 6, 1, 7.0); // B7
+               addCell(sheet1, 7, 1, 8.0); // B8
+               addCell(sheet1, 67, 1, 9.0); // B68
+               addCell(sheet1, 68, 1, 10.0); // B69
+
+               double expectedResult = (4.0 * 8.0 + 5.0 * 9.0) / 10.0;
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv = fe.evaluate(cell);
+
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(expectedResult, cv.getNumberValue(), 0.0);
+       }
+
+       private static void addCell(HSSFSheet sheet, int rowIx, int colIx,
+                       double value) {
+               sheet.createRow(rowIx).createCell(colIx).setCellValue(value);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestFormulasFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/eval/TestFormulasFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..fd0771f
--- /dev/null
@@ -0,0 +1,310 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import java.io.PrintStream;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.functions.TestMathX;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+
+/**
+ * Tests formulas and operators as loaded from a test data spreadsheet.<p/>
+ * This class does not test implementors of <tt>Function</tt> and <tt>OperationEval</tt> in
+ * isolation.  Much of the evaluation engine (i.e. <tt>HSSFFormulaEvaluator</tt>, ...) gets
+ * exercised as well.  Tests for bug fixes and specific/tricky behaviour can be found in the
+ * corresponding test class (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor,
+ * where execution can be observed more easily.
+ *
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ */
+public final class TestFormulasFromSpreadsheet extends TestCase {
+
+       private static final class Result {
+               public static final int SOME_EVALUATIONS_FAILED = -1;
+               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
+               public static final int NO_EVALUATIONS_FOUND = 0;
+       }
+
+       /**
+        * This class defines constants for navigating around the test data spreadsheet used for these tests.
+        */
+       private static final class SS {
+
+               /**
+                * Name of the test spreadsheet (found in the standard test data folder)
+                */
+               public final static String FILENAME = "FormulaEvalTestData.xls";
+               /**
+                * Row (zero-based) in the test spreadsheet where the operator examples start.
+                */
+               public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
+               /**
+                * Row (zero-based) in the test spreadsheet where the function examples start.
+                */
+               public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
+               /**
+                * Index of the column that contains the function names
+                */
+               public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
+
+               /**
+                * Used to indicate when there are no more functions left
+                */
+               public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
+
+               /**
+                * Index of the column where the test values start (for each function)
+                */
+               public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
+
+               /**
+                * Each function takes 4 rows in the test spreadsheet
+                */
+               public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
+       }
+
+       private HSSFWorkbook workbook;
+       private Sheet sheet;
+       // Note - multiple failures are aggregated before ending.
+       // If one or more functions fail, a single AssertionFailedError is thrown at the end
+       private int _functionFailureCount;
+       private int _functionSuccessCount;
+       private int _evaluationFailureCount;
+       private int _evaluationSuccessCount;
+
+       private static final Cell getExpectedValueCell(Row row, int columnIndex) {
+               if (row == null) {
+                       return null;
+               }
+               return row.getCell(columnIndex);
+       }
+
+
+       private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) {
+               if (expected == null) {
+                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
+               }
+               if(actual == null) {
+                       throw new AssertionFailedError(msg + " - actual value was null");
+               }
+
+               switch (expected.getCellType()) {
+                       case Cell.CELL_TYPE_BLANK:
+                               assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
+                               break;
+                       case Cell.CELL_TYPE_BOOLEAN:
+                               assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType());
+                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
+                               break;
+                       case Cell.CELL_TYPE_ERROR:
+                               assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType());
+                               assertEquals(msg, ErrorEval.getText(expected.getErrorCellValue()), ErrorEval.getText(actual.getErrorValue()));
+                               break;
+                       case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
+                               throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
+                       case Cell.CELL_TYPE_NUMERIC:
+                               assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
+                               TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
+                               break;
+                       case Cell.CELL_TYPE_STRING:
+                               assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
+                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
+                               break;
+               }
+       }
+
+
+       protected void setUp() {
+               if (workbook == null) {
+                       workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
+                       sheet = workbook.getSheetAt( 0 );
+               }
+               _functionFailureCount = 0;
+               _functionSuccessCount = 0;
+               _evaluationFailureCount = 0;
+               _evaluationSuccessCount = 0;
+       }
+
+       public void testFunctionsFromTestSpreadsheet() {
+
+               processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
+               processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
+               // example for debugging individual functions/operators:
+//             processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
+//             processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
+
+               // confirm results
+               String successMsg = "There were "
+                               + _evaluationSuccessCount + " successful evaluation(s) and "
+                               + _functionSuccessCount + " function(s) without error";
+               if(_functionFailureCount > 0) {
+                       String msg = _functionFailureCount + " function(s) failed in "
+                       + _evaluationFailureCount + " evaluation(s).  " + successMsg;
+                       throw new AssertionFailedError(msg);
+               }
+               if(false) { // normally no output for successful tests
+                       System.out.println(getClass().getName() + ": " + successMsg);
+               }
+       }
+
+       /**
+        * @param startRowIndex row index in the spreadsheet where the first function/operator is found
+        * @param testFocusFunctionName name of a single function/operator to test alone.
+        * Typically pass <code>null</code> to test all functions
+        */
+       private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
+               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
+
+               int rowIndex = startRowIndex;
+               while (true) {
+                       Row r = sheet.getRow(rowIndex);
+                       String targetFunctionName = getTargetFunctionName(r);
+                       if(targetFunctionName == null) {
+                               throw new AssertionFailedError("Test spreadsheet cell empty on row ("
+                                               + (rowIndex+1) + "). Expected function name or '"
+                                               + SS.FUNCTION_NAMES_END_SENTINEL + "'");
+                       }
+                       if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
+                               // found end of functions list
+                               break;
+                       }
+                       if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
+
+                               // expected results are on the row below
+                               Row expectedValuesRow = sheet.getRow(rowIndex + 1);
+                               if(expectedValuesRow == null) {
+                                       int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
+                                       throw new AssertionFailedError("Missing expected values row for function '"
+                                                       + targetFunctionName + " (row " + missingRowNum + ")");
+                               }
+                               switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
+                                       case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
+                                       case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
+                                       default:
+                                               throw new RuntimeException("unexpected result");
+                                       case Result.NO_EVALUATIONS_FOUND: // do nothing
+                               }
+                       }
+                       rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
+               }
+       }
+
+       /**
+        *
+        * @return a constant from the local Result class denoting whether there were any evaluation
+        * cases, and whether they all succeeded.
+        */
+       private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName,
+                       Row formulasRow, Row expectedValuesRow) {
+
+               int result = Result.NO_EVALUATIONS_FOUND; // so far
+               short endcolnum = formulasRow.getLastCellNum();
+
+               // iterate across the row for all the evaluation cases
+               for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
+                       Cell c = formulasRow.getCell(colnum);
+                       if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
+                               continue;
+                       }
+
+                       CellValue actualValue = evaluator.evaluate(c);
+
+                       Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum);
+                       try {
+                               confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
+                                               expectedValueCell, actualValue);
+                               _evaluationSuccessCount ++;
+                               if(result != Result.SOME_EVALUATIONS_FAILED) {
+                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
+                               }
+                       } catch (AssertionFailedError e) {
+                               _evaluationFailureCount ++;
+                               printShortStackTrace(System.err, e);
+                               result = Result.SOME_EVALUATIONS_FAILED;
+                       }
+               }
+               return result;
+       }
+
+       /**
+        * Useful to keep output concise when expecting many failures to be reported by this test case
+        */
+       private static void printShortStackTrace(PrintStream ps, AssertionFailedError e) {
+               StackTraceElement[] stes = e.getStackTrace();
+
+               int startIx = 0;
+               // skip any top frames inside junit.framework.Assert
+               while(startIx<stes.length) {
+                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
+                               break;
+                       }
+                       startIx++;
+               }
+               // skip bottom frames (part of junit framework)
+               int endIx = startIx+1;
+               while(endIx < stes.length) {
+                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
+                               break;
+                       }
+                       endIx++;
+               }
+               if(startIx >= endIx) {
+                       // something went wrong. just print the whole stack trace
+                       e.printStackTrace(ps);
+               }
+               endIx -= 4; // skip 4 frames of reflection invocation
+               ps.println(e.toString());
+               for(int i=startIx; i<endIx; i++) {
+                       ps.println("\tat " + stes[i].toString());
+               }
+       }
+
+       /**
+        * @return <code>null</code> if cell is missing, empty or blank
+        */
+       private static String getTargetFunctionName(Row r) {
+               if(r == null) {
+                       System.err.println("Warning - given null row, can't figure out function name");
+                       return null;
+               }
+               Cell cell = r.getCell(SS.COLUMN_INDEX_FUNCTION_NAME);
+               if(cell == null) {
+                       System.err.println("Warning - Row " + r.getRowNum() + " has no cell " + SS.COLUMN_INDEX_FUNCTION_NAME + ", can't figure out function name");
+                       return null;
+               }
+               if(cell.getCellType() == Cell.CELL_TYPE_BLANK) {
+                       return null;
+               }
+               if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
+                       return cell.getRichStringCellValue().getString();
+               }
+
+               throw new AssertionFailedError("Bad cell type for 'function name' column: ("
+                               + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestMinusZeroResult.java b/src/testcases/org/apache/poi/ss/formula/eval/TestMinusZeroResult.java
new file mode 100644 (file)
index 0000000..656c47d
--- /dev/null
@@ -0,0 +1,151 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.ComparisonFailure;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.functions.Function;
+import org.apache.poi.util.HexDump;
+
+/**
+ * IEEE 754 defines a quantity '-0.0' which is distinct from '0.0'.
+ * Negative zero is not easy to observe in Excel, since it is usually converted to 0.0.
+ * (Note - the results of XLL add-in functions don't seem to be converted, so they are one
+ * reliable avenue to observe Excel's treatment of '-0.0' as an operand.)
+ * <p/>
+ * POI attempts to emulate Excel faithfully, so this class tests
+ * two aspects of '-0.0' in formula evaluation:
+ * <ol>
+ * <li>For most operation results '-0.0' is converted to '0.0'.</li>
+ * <li>Comparison operators have slightly different rules regarding '-0.0'.</li>
+ * </ol>
+ * @author Josh Micich
+ */
+public final class TestMinusZeroResult extends TestCase {
+       private static final double MINUS_ZERO = -0.0;
+
+       // convenient access to namepace
+       private static final EvalInstances EI = null;
+
+       public void testSimpleOperators() {
+
+               // unary plus is a no-op
+               checkEval(MINUS_ZERO, UnaryPlusEval.instance, MINUS_ZERO);
+
+               // most simple operators convert -0.0 to +0.0
+               checkEval(0.0, EI.UnaryMinus, 0.0);
+               checkEval(0.0, EI.Percent, MINUS_ZERO);
+               checkEval(0.0, EI.Multiply, MINUS_ZERO, 1.0);
+               checkEval(0.0, EI.Divide, MINUS_ZERO, 1.0);
+               checkEval(0.0, EI.Power, MINUS_ZERO, 1.0);
+
+               // but SubtractEval does not convert -0.0, so '-' and '+' work like java
+               checkEval(MINUS_ZERO, EI.Subtract, MINUS_ZERO, 0.0); // this is the main point of bug 47198
+               checkEval(0.0, EI.Add, MINUS_ZERO, 0.0);
+       }
+
+       /**
+        * These results are hard to see in Excel (since -0.0 is usually converted to +0.0 before it
+        * gets to the comparison operator)
+        */
+       public void testComparisonOperators() {
+               checkEval(false, EI.Equal, 0.0, MINUS_ZERO);
+               checkEval(true, EI.GreaterThan, 0.0, MINUS_ZERO);
+               checkEval(true, EI.LessThan, MINUS_ZERO, 0.0);
+       }
+
+       public void testTextRendering() {
+               confirmTextRendering("-0", MINUS_ZERO);
+               // sub-normal negative numbers also display as '-0'
+               confirmTextRendering("-0", Double.longBitsToDouble(0x8000100020003000L));
+       }
+
+       /**
+        * Uses {@link ConcatEval} to force number-to-text conversion
+        */
+       private static void confirmTextRendering(String expRendering, double d) {
+               ValueEval[] args = { StringEval.EMPTY_INSTANCE, new NumberEval(d), };
+               StringEval se = (StringEval) EI.Concat.evaluate(args, -1, (short)-1);
+               String result = se.getStringValue();
+               assertEquals(expRendering, result);
+       }
+
+       private static void checkEval(double expectedResult, Function instance, double... dArgs) {
+               NumberEval result = (NumberEval) evaluate(instance, dArgs);
+               assertDouble(expectedResult, result.getNumberValue());
+       }
+       private static void checkEval(boolean expectedResult, Function instance, double... dArgs) {
+               BoolEval result = (BoolEval) evaluate(instance, dArgs);
+               assertEquals(expectedResult, result.getBooleanValue());
+       }
+       private static ValueEval evaluate(Function instance, double... dArgs) {
+               ValueEval[] evalArgs;
+               evalArgs = new ValueEval[dArgs.length];
+               for (int i = 0; i < evalArgs.length; i++) {
+                       evalArgs[i] = new NumberEval(dArgs[i]);
+               }
+               ValueEval r = instance.evaluate(evalArgs, -1, (short)-1);
+               return r;
+       }
+
+       /**
+        * Not really a POI test - just shows similar behaviour of '-0.0' in Java.
+        */
+       public void testJava() {
+
+               assertEquals(0x8000000000000000L, Double.doubleToLongBits(MINUS_ZERO));
+
+               // The simple operators consider all zeros to be the same
+               assertTrue(MINUS_ZERO == MINUS_ZERO);
+               assertTrue(MINUS_ZERO == +0.0);
+               assertFalse(MINUS_ZERO < +0.0);
+
+               // Double.compare() considers them different
+               assertTrue(Double.compare(MINUS_ZERO, +0.0) < 0);
+
+               // multiplying zero by any negative quantity yields minus zero
+               assertDouble(MINUS_ZERO, 0.0*-1);
+               assertDouble(MINUS_ZERO, 0.0*-1e300);
+               assertDouble(MINUS_ZERO, 0.0*-1e-300);
+
+               // minus zero can be produced as a result of underflow
+               assertDouble(MINUS_ZERO, -1e-300 / 1e100);
+
+               // multiplying or dividing minus zero by a positive quantity yields minus zero
+               assertDouble(MINUS_ZERO, MINUS_ZERO * 1.0);
+               assertDouble(MINUS_ZERO, MINUS_ZERO / 1.0);
+
+               // subtracting positive zero gives minus zero
+               assertDouble(MINUS_ZERO, MINUS_ZERO - 0.0);
+               // BUT adding positive zero gives positive zero
+               assertDouble(0.0, MINUS_ZERO + 0.0);  // <<----
+       }
+
+       /**
+        * Just so there is no ambiguity.  The two double values have to be exactly equal
+        */
+       private static void assertDouble(double a, double b) {
+               long bitsA = Double.doubleToLongBits(a);
+               long bitsB = Double.doubleToLongBits(b);
+               if (bitsA != bitsB) {
+                       throw new ComparisonFailure("value different to expected",
+                                       new String(HexDump.longToHex(bitsA)), new String(HexDump.longToHex(bitsB)));
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestMissingArgEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestMissingArgEval.java
new file mode 100644 (file)
index 0000000..2bef73c
--- /dev/null
@@ -0,0 +1,74 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import java.util.EmptyStackException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Tests for {@link MissingArgEval}
+ *
+ * @author Josh Micich
+ */
+public final class TestMissingArgEval extends TestCase {
+       
+       public void testEvaluateMissingArgs() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+               HSSFCell cell = sheet.createRow(0).createCell(0);
+               
+               cell.setCellFormula("if(true,)"); 
+               fe.clearAllCachedResultValues();
+               CellValue cv;
+               try {
+                       cv = fe.evaluate(cell);
+               } catch (EmptyStackException e) {
+                       throw new AssertionFailedError("Missing args evaluation not implemented (bug 43354");
+               }
+               // MissingArg -> BlankEval -> zero (as formula result)
+               assertEquals(0.0, cv.getNumberValue(), 0.0);
+               
+               // MissingArg -> BlankEval -> empty string (in concatenation)
+               cell.setCellFormula("\"abc\"&if(true,)"); 
+               fe.clearAllCachedResultValues();
+               assertEquals("abc", fe.evaluate(cell).getStringValue());
+       }
+       
+       public void testCountFuncs() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+               HSSFCell cell = sheet.createRow(0).createCell(0);
+               
+               cell.setCellFormula("COUNT(C5,,,,)"); // 4 missing args, C5 is blank 
+               assertEquals(4.0, fe.evaluate(cell).getNumberValue(), 0.0);
+
+               cell.setCellFormula("COUNTA(C5,,)"); // 2 missing args, C5 is blank 
+               fe.clearAllCachedResultValues();
+               assertEquals(2.0, fe.evaluate(cell).getNumberValue(), 0.0);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestOperandResolver.java b/src/testcases/org/apache/poi/ss/formula/eval/TestOperandResolver.java
new file mode 100644 (file)
index 0000000..4e24f84
--- /dev/null
@@ -0,0 +1,89 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/**
+ * Tests for <tt>OperandResolver</tt>
+ *
+ * @author Brendan Nolan
+ */
+public final class TestOperandResolver extends TestCase {
+
+       public void testParseDouble_bug48472() {
+               
+               String value = "-";
+               
+               Double resolvedValue = null;
+               
+               try {
+                       resolvedValue = OperandResolver.parseDouble(value);
+               } catch (StringIndexOutOfBoundsException e) { 
+                       throw new AssertionFailedError("Identified bug 48472");
+               }
+               
+               assertEquals(null, resolvedValue);
+               
+       }
+       
+       public void testParseDouble_bug49723() {
+               
+               String value = ".1";
+               
+               Double resolvedValue = null;
+               
+               resolvedValue = OperandResolver.parseDouble(value);
+               
+               assertNotNull("Identified bug 49723", resolvedValue);
+               
+       }
+       
+       /**
+        * 
+        * Tests that a list of valid strings all return a non null value from {@link OperandResolver#parseDouble(String)}
+        * 
+        */
+       public void testParseDoubleValidStrings() {
+                               
+               String[] values = new String[]{".19", "0.19", "1.9", "1E4", "-.19", "-0.19", "8.5","-1E4", ".5E6","+1.5","+1E5", "  +1E5  "};
+               
+               for (String value : values) {
+                       assertTrue(OperandResolver.parseDouble(value) != null);
+                       assertEquals(OperandResolver.parseDouble(value), Double.parseDouble(value));
+               }
+
+       }
+       
+       /**
+        * 
+        * Tests that a list of invalid strings all return null from {@link OperandResolver#parseDouble(String)}
+        * 
+        */
+       public void testParseDoubleInvalidStrings() {
+               
+               String[] values = new String[]{"-", "ABC", "-X", "1E5a", "Infinity", "NaN", ".5F", "1,000"};
+               
+               for (String value : values) {
+                       assertEquals(null, OperandResolver.parseDouble(value));
+               }
+
+       }
+       
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestPercentEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestPercentEval.java
new file mode 100644 (file)
index 0000000..faeee6a
--- /dev/null
@@ -0,0 +1,83 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.functions.EvalFactory;
+import org.apache.poi.ss.formula.functions.NumericFunctionInvoker;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Test for percent operator evaluator.
+ *
+ * @author Josh Micich
+ */
+public final class TestPercentEval extends TestCase {
+
+       private static void confirm(ValueEval arg, double expectedResult) {
+               ValueEval[] args = {
+                       arg,
+               };
+
+               double result = NumericFunctionInvoker.invoke(PercentEval.instance, args, 0, 0);
+
+               assertEquals(expectedResult, result, 0);
+       }
+
+       public void testBasic() {
+               confirm(new NumberEval(5), 0.05);
+               confirm(new NumberEval(3000), 30.0);
+               confirm(new NumberEval(-150), -1.5);
+               confirm(new StringEval("0.2"), 0.002);
+               confirm(BoolEval.TRUE, 0.01);
+       }
+
+       public void test1x1Area() {
+               AreaEval ae = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
+               confirm(ae, 0.5);
+       }
+       public void testInSpreadSheet() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+               HSSFRow row = sheet.createRow(0);
+               HSSFCell cell = row.createCell(0);
+               cell.setCellFormula("B1%");
+               row.createCell(1).setCellValue(50.0);
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv;
+               try {
+                       cv = fe.evaluate(cell);
+               } catch (RuntimeException e) {
+                       if(e.getCause() instanceof NullPointerException) {
+                               throw new AssertionFailedError("Identified bug 44608");
+                       }
+                       // else some other unexpected error
+                       throw e;
+               }
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
+               assertEquals(0.5, cv.getNumberValue(), 0.0);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestRangeEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestRangeEval.java
new file mode 100644 (file)
index 0000000..439d642
--- /dev/null
@@ -0,0 +1,160 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.AreaI;
+import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.AreaReference;
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.ss.formula.TwoDEval;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Test for unary plus operator evaluator.
+ *
+ * @author Josh Micich
+ */
+public final class TestRangeEval extends TestCase {
+
+       public void testPermutations() {
+
+               confirm("B3", "D7", "B3:D7");
+               confirm("B1", "B1", "B1:B1");
+
+               confirm("B7", "D3", "B3:D7");
+               confirm("D3", "B7", "B3:D7");
+               confirm("D7", "B3", "B3:D7");
+       }
+
+       private static void confirm(String refA, String refB, String expectedAreaRef) {
+
+               ValueEval[] args = {
+                       createRefEval(refA),
+                       createRefEval(refB),
+               };
+               AreaReference ar = new AreaReference(expectedAreaRef);
+               ValueEval result = EvalInstances.Range.evaluate(args, 0, (short)0);
+               assertTrue(result instanceof AreaEval);
+               AreaEval ae = (AreaEval) result;
+               assertEquals(ar.getFirstCell().getRow(), ae.getFirstRow());
+               assertEquals(ar.getLastCell().getRow(), ae.getLastRow());
+               assertEquals(ar.getFirstCell().getCol(), ae.getFirstColumn());
+               assertEquals(ar.getLastCell().getCol(), ae.getLastColumn());
+       }
+
+       private static ValueEval createRefEval(String refStr) {
+               CellReference cr = new CellReference(refStr);
+               return new MockRefEval(cr.getRow(), cr.getCol());
+
+       }
+
+       private static final class MockRefEval extends RefEvalBase {
+
+               public MockRefEval(int rowIndex, int columnIndex) {
+                       super(rowIndex, columnIndex);
+               }
+               public ValueEval getInnerValueEval() {
+                       throw new RuntimeException("not expected to be called during this test");
+               }
+               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
+                               int relLastColIx) {
+                       AreaI area = new OffsetArea(getRow(), getColumn(),
+                                       relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+                       return new MockAreaEval(area);
+               }
+       }
+
+       private static final class MockAreaEval extends AreaEvalBase {
+
+               public MockAreaEval(AreaI ptg) {
+                       super(ptg);
+               }
+               private MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn) {
+                       super(firstRow, firstColumn, lastRow, lastColumn);
+               }
+               public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
+                       throw new RuntimeException("not expected to be called during this test");
+               }
+               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx,
+                               int relLastColIx) {
+                       AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
+                                       relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+
+                       return new MockAreaEval(area);
+               }
+               public TwoDEval getRow(int rowIndex) {
+                       if (rowIndex >= getHeight()) {
+                               throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+                                               + ".  Allowable range is (0.." + getHeight() + ").");
+                       }
+                       return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn());
+               }
+               public TwoDEval getColumn(int columnIndex) {
+                       if (columnIndex >= getWidth()) {
+                               throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
+                                               + ".  Allowable range is (0.." + getWidth() + ").");
+                       }
+                       return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex);
+               }
+       }
+
+       public void testRangeUsingOffsetFunc_bug46948() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFRow row = wb.createSheet("Sheet1").createRow(0);
+               HSSFCell cellA1 = row.createCell(0);
+               HSSFCell cellB1 = row.createCell(1);
+               row.createCell(2).setCellValue(5.0); // C1
+               row.createCell(3).setCellValue(7.0); // D1
+               row.createCell(4).setCellValue(9.0); // E1
+
+
+               cellA1.setCellFormula("SUM(C1:OFFSET(C1,0,B1))");
+
+               cellB1.setCellValue(1.0); // range will be C1:D1
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               CellValue cv;
+               try {
+                       cv = fe.evaluate(cellA1);
+               } catch (IllegalArgumentException e) {
+                       if (e.getMessage().equals("Unexpected ref arg class (org.apache.poi.ss.formula.LazyAreaEval)")) {
+                               throw new AssertionFailedError("Identified bug 46948");
+                       }
+                       throw e;
+               }
+
+               assertEquals(12.0, cv.getNumberValue(), 0.0);
+
+               cellB1.setCellValue(2.0); // range will be C1:E1
+               fe.notifyUpdateCell(cellB1);
+               cv = fe.evaluate(cellA1);
+               assertEquals(21.0, cv.getNumberValue(), 0.0);
+
+               cellB1.setCellValue(0.0); // range will be C1:C1
+               fe.notifyUpdateCell(cellB1);
+               cv = fe.evaluate(cellA1);
+               assertEquals(5.0, cv.getNumberValue(), 0.0);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/TestUnaryPlusEval.java b/src/testcases/org/apache/poi/ss/formula/eval/TestUnaryPlusEval.java
new file mode 100644 (file)
index 0000000..33022ad
--- /dev/null
@@ -0,0 +1,58 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.eval;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.ss.formula.functions.EvalFactory;
+import org.apache.poi.ss.formula.functions.NumericFunctionInvoker;
+
+/**
+ * Test for unary plus operator evaluator.
+ *
+ * @author Josh Micich
+ */
+public final class TestUnaryPlusEval extends TestCase {
+
+       /**
+        * Test for bug observable at svn revision 618865 (5-Feb-2008)<br/>
+        * The code for handling column operands had been copy-pasted from the row handling code.
+        */
+       public void testColumnOperand() {
+
+               short firstRow = (short)8;
+               short lastRow = (short)12;
+               short colNum = (short)5;
+               AreaPtg areaPtg = new AreaPtg(firstRow, lastRow, colNum, colNum, false, false, false, false);
+               ValueEval[] values = {
+                               new NumberEval(27),
+                               new NumberEval(29),
+                               new NumberEval(35),     // value in row 10
+                               new NumberEval(37),
+                               new NumberEval(38),
+               };
+               ValueEval[] args = {
+                       EvalFactory.createAreaEval(areaPtg, values),
+               };
+
+               double result = NumericFunctionInvoker.invoke(EvalInstances.UnaryPlus, args, 10, (short)20);
+
+               assertEquals(35, result, 0);
+       }
+}
index 1e4806982873f260d7a5e420fcf84942f9edd45a..505ea127b7c952646730ee5ab3273580288aceb8 100644 (file)
@@ -20,7 +20,7 @@ package org.apache.poi.ss.formula.eval.forked;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
 import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
diff --git a/src/testcases/org/apache/poi/ss/formula/function/AllFormulaFunctionTests.java b/src/testcases/org/apache/poi/ss/formula/function/AllFormulaFunctionTests.java
new file mode 100644 (file)
index 0000000..5bbf8f0
--- /dev/null
@@ -0,0 +1,37 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.function;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Collects all tests for this <tt>org.apache.poi.hssf.record.formula.function</tt>.
+ * 
+ * @author Josh Micich
+ */
+public class AllFormulaFunctionTests {
+       
+       public static Test suite() {
+               TestSuite result = new TestSuite(AllFormulaFunctionTests.class.getName());
+               result.addTestSuite(TestFunctionMetadataRegistry.class);
+               result.addTestSuite(TestParseMissingBuiltInFuncs.class);
+               result.addTestSuite(TestReadMissingBuiltInFuncs.class);
+               return result;
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java b/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java
new file mode 100644 (file)
index 0000000..4d6877f
--- /dev/null
@@ -0,0 +1,617 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.function;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * This class is not used during normal POI run-time but is used at development time to generate
+ * the file 'functionMetadata.txt'.   There are more than 300 built-in functions in Excel and the
+ * intention of this class is to make it easier to maintain the metadata, by extracting it from
+ * a reliable source.
+ *
+ * @author Josh Micich
+ */
+public final class ExcelFileFormatDocFunctionExtractor {
+
+       private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
+
+       /**
+        * For simplicity, the output file is strictly simple ASCII.
+        * This method detects any unexpected characters.
+        */
+       /* package */ static boolean isSimpleAscii(char c) {
+
+               if (c>=0x21 && c<=0x7E) {
+                       // everything from '!' to '~' (includes letters, digits, punctuation
+                       return true;
+               }
+               // some specific whitespace chars below 0x21:
+               switch(c) {
+                       case ' ':
+                       case '\t':
+                       case '\r':
+                       case '\n':
+                               return true;
+               }
+               return false;
+       }
+
+
+       private static final class FunctionData {
+               // special characters from the ooo document
+               private static final int CHAR_ELLIPSIS_8230 = 8230;
+               private static final int CHAR_NDASH_8211 = 8211;
+
+               private final int _index;
+               private final boolean _hasFootnote;
+               private final String _name;
+               private final int _minParams;
+               private final int _maxParams;
+               private final String _returnClass;
+               private final String _paramClasses;
+               private final boolean _isVolatile;
+
+               public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
+                                       String returnClass, String paramClasses, boolean isVolatile) {
+                       _index = funcIx;
+                       _hasFootnote = hasFootnote;
+                       _name = funcName;
+                       _minParams = minParams;
+                       _maxParams = maxParams;
+                       _returnClass = convertSpecialChars(returnClass);
+                       _paramClasses = convertSpecialChars(paramClasses);
+                       _isVolatile = isVolatile;
+               }
+               private static String convertSpecialChars(String ss) {
+                       StringBuffer sb = new StringBuffer(ss.length() + 4);
+                       for(int i=0; i<ss.length(); i++) {
+                               char c = ss.charAt(i);
+                               if (isSimpleAscii(c)) {
+                                       sb.append(c);
+                                       continue;
+                               }
+                               switch (c) {
+                                       case CHAR_NDASH_8211:
+                                               sb.append('-');
+                                               continue;
+                                       case CHAR_ELLIPSIS_8230:
+                                               sb.append("...");
+                                               continue;
+                               }
+                               throw new RuntimeException("bad char (" + ((int)c) + ") in string '" + ss + "'");
+                       }
+                       return sb.toString();
+               }
+               public int getIndex() {
+                       return _index;
+               }
+               public String getName() {
+                       return _name;
+               }
+               public boolean hasFootnote() {
+                       return _hasFootnote;
+               }
+               public String formatAsDataLine() {
+                       return _index + "\t" + _name + "\t" + _minParams + "\t"
+                                       + _maxParams + "\t" + _returnClass + "\t" + _paramClasses
+                                       + "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote);
+               }
+               private static String checkMark(boolean b) {
+                       return b ? "x" : "";
+               }
+       }
+
+       private static final class FunctionDataCollector {
+
+               private final Map _allFunctionsByIndex;
+               private final Map _allFunctionsByName;
+               private final Set _groupFunctionIndexes;
+               private final Set _groupFunctionNames;
+               private final PrintStream _ps;
+
+               public FunctionDataCollector(PrintStream ps) {
+                       _ps = ps;
+                       _allFunctionsByIndex = new HashMap();
+                       _allFunctionsByName = new HashMap();
+                       _groupFunctionIndexes = new HashSet();
+                       _groupFunctionNames = new HashSet();
+               }
+
+               public void addFuntion(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
+                               String returnClass, String paramClasses, String volatileFlagStr) {
+                       boolean isVolatile = volatileFlagStr.length() > 0;
+
+                       Integer funcIxKey = Integer.valueOf(funcIx);
+                       if(!_groupFunctionIndexes.add(funcIxKey)) {
+                               throw new RuntimeException("Duplicate function index (" + funcIx + ")");
+                       }
+                       if(!_groupFunctionNames.add(funcName)) {
+                               throw new RuntimeException("Duplicate function name '" + funcName + "'");
+                       }
+
+                       checkRedefinedFunction(hasFootnote, funcName, funcIxKey);
+                       FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName,
+                                       minParams, maxParams, returnClass, paramClasses, isVolatile);
+
+                       _allFunctionsByIndex.put(funcIxKey, fd);
+                       _allFunctionsByName.put(funcName, fd);
+               }
+
+               /**
+                * Some extra validation here.
+                * Any function which changes definition will have a footnote in the source document
+                */
+               private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) {
+                       FunctionData fdPrev;
+                       // check by index
+                       fdPrev = (FunctionData) _allFunctionsByIndex.get(funcIxKey);
+                       if(fdPrev != null) {
+                               if(!fdPrev.hasFootnote() || !hasNote) {
+                                       throw new RuntimeException("changing function ["
+                                                       + funcIxKey + "] definition without foot-note");
+                               }
+                               _allFunctionsByName.remove(fdPrev.getName());
+                       }
+                       // check by name
+                       fdPrev = (FunctionData) _allFunctionsByName.get(funcName);
+                       if(fdPrev != null) {
+                               if(!fdPrev.hasFootnote() || !hasNote) {
+                                       throw new RuntimeException("changing function '"
+                                                       + funcName + "' definition without foot-note");
+                               }
+                               _allFunctionsByIndex.remove(Integer.valueOf(fdPrev.getIndex()));
+                       }
+               }
+
+               public void endTableGroup(String headingText) {
+                       Integer[] keys = new Integer[_groupFunctionIndexes.size()];
+                       _groupFunctionIndexes.toArray(keys);
+                       _groupFunctionIndexes.clear();
+                       _groupFunctionNames.clear();
+                       Arrays.sort(keys);
+
+                       _ps.println("# " + headingText);
+                       for (int i = 0; i < keys.length; i++) {
+                               FunctionData fd = (FunctionData) _allFunctionsByIndex.get(keys[i]);
+                               _ps.println(fd.formatAsDataLine());
+                       }
+               }
+       }
+
+       /**
+        * To avoid drag-in - parse XML using only JDK.
+        */
+       private static class EFFDocHandler implements ContentHandler {
+               private static final String[] HEADING_PATH_NAMES = {
+                       "office:document-content", "office:body", "office:text", "text:h",
+               };
+               private static final String[] TABLE_BASE_PATH_NAMES = {
+                       "office:document-content", "office:body", "office:text", "table:table",
+               };
+               private static final String[] TABLE_ROW_RELPATH_NAMES = {
+                       "table:table-row",
+               };
+               private static final String[] TABLE_CELL_RELPATH_NAMES = {
+                       "table:table-row", "table:table-cell", "text:p",
+               };
+               // after May 2008 there was one more style applied to the footnotes
+               private static final String[] NOTE_REF_RELPATH_NAMES_OLD = {
+                       "table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
+               };
+               private static final String[] NOTE_REF_RELPATH_NAMES = {
+                       "table:table-row", "table:table-cell", "text:p", "text:span", "text:span", "text:note-ref",
+               };
+
+
+               private final Stack _elemNameStack;
+               /** <code>true</code> only when parsing the target tables */
+               private boolean _isInsideTable;
+
+               private final List _rowData;
+               private final StringBuffer _textNodeBuffer;
+               private final List _rowNoteFlags;
+               private boolean _cellHasNote;
+
+               private final FunctionDataCollector _fdc;
+               private String _lastHeadingText;
+
+               public EFFDocHandler(FunctionDataCollector fdc) {
+                       _fdc = fdc;
+                       _elemNameStack = new Stack();
+                       _isInsideTable = false;
+                       _rowData = new ArrayList();
+                       _textNodeBuffer = new StringBuffer();
+                       _rowNoteFlags = new ArrayList();
+               }
+
+               private boolean matchesTargetPath() {
+                       return matchesPath(0, TABLE_BASE_PATH_NAMES);
+               }
+               private boolean matchesRelPath(String[] pathNames) {
+                       return matchesPath(TABLE_BASE_PATH_NAMES.length, pathNames);
+               }
+               private boolean matchesPath(int baseStackIndex, String[] pathNames) {
+                       if(_elemNameStack.size() != baseStackIndex + pathNames.length) {
+                               return false;
+                       }
+                       for (int i = 0; i < pathNames.length; i++) {
+                               if(!_elemNameStack.get(baseStackIndex + i).equals(pathNames[i])) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               public void characters(char[] ch, int start, int length) {
+                       // only 2 text nodes where text is collected:
+                       if(matchesRelPath(TABLE_CELL_RELPATH_NAMES) || matchesPath(0, HEADING_PATH_NAMES)) {
+                               _textNodeBuffer.append(ch, start, length);
+                       }
+               }
+
+               public void endElement(String namespaceURI, String localName, String name) {
+                       String expectedName = (String) _elemNameStack.peek();
+                       if(expectedName != name) {
+                               throw new RuntimeException("close tag mismatch");
+                       }
+                       if(matchesPath(0, HEADING_PATH_NAMES)) {
+                               _lastHeadingText = _textNodeBuffer.toString().trim();
+                               _textNodeBuffer.setLength(0);
+                       }
+                       if(_isInsideTable) {
+                               if(matchesTargetPath()) {
+                                       _fdc.endTableGroup(_lastHeadingText);
+                                       _isInsideTable = false;
+                               } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
+                                       String[] cellData = new String[_rowData.size()];
+                                       _rowData.toArray(cellData);
+                                       _rowData.clear();
+                                       Boolean[] noteFlags = new Boolean[_rowNoteFlags.size()];
+                                       _rowNoteFlags.toArray(noteFlags);
+                                       _rowNoteFlags.clear();
+                                       processTableRow(cellData, noteFlags);
+                               } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
+                                       _rowData.add(_textNodeBuffer.toString().trim());
+                                       _rowNoteFlags.add(Boolean.valueOf(_cellHasNote));
+                                       _textNodeBuffer.setLength(0);
+                               }
+                       }
+                       _elemNameStack.pop();
+               }
+
+               private void processTableRow(String[] cellData, Boolean[] noteFlags) {
+                       // each table row of the document contains data for two functions
+                       if(cellData.length != 15) {
+                               throw new RuntimeException("Bad table row size");
+                       }
+                       processFunction(cellData, noteFlags, 0);
+                       processFunction(cellData, noteFlags, 8);
+               }
+               public void processFunction(String[] cellData, Boolean[] noteFlags, int i) {
+                       String funcIxStr = cellData[i + 0];
+                       if (funcIxStr.length() < 1) {
+                               // empty (happens on the right hand side when there is an odd number of functions)
+                               return;
+                       }
+                       int funcIx = parseInt(funcIxStr);
+
+                       boolean hasFootnote = noteFlags[i + 1].booleanValue();
+                       String funcName = cellData[i + 1];
+                       int minParams = parseInt(cellData[i + 2]);
+                       int maxParams = parseInt(cellData[i + 3]);
+
+                       String returnClass = cellData[i + 4];
+                       String paramClasses = cellData[i + 5];
+                       String volatileFlagStr = cellData[i + 6];
+
+                       _fdc.addFuntion(funcIx, hasFootnote, funcName, minParams, maxParams, returnClass, paramClasses, volatileFlagStr);
+               }
+               private static int parseInt(String valStr) {
+                       try {
+                               return Integer.parseInt(valStr);
+                       } catch (NumberFormatException e) {
+                               throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer");
+                       }
+               }
+               public void startElement(String namespaceURI, String localName, String name, Attributes atts) {
+                       _elemNameStack.add(name);
+                       if(matchesTargetPath()) {
+                               String tableName = atts.getValue("table:name");
+                               if(tableName.startsWith("tab_fml_func") && !tableName.equals("tab_fml_func0")) {
+                                       _isInsideTable = true;
+                               }
+                               return;
+                       }
+                       if(matchesPath(0, HEADING_PATH_NAMES)) {
+                               _textNodeBuffer.setLength(0);
+                       } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) {
+                               _rowData.clear();
+                               _rowNoteFlags.clear();
+                       } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) {
+                               _textNodeBuffer.setLength(0);
+                               _cellHasNote = false;
+                       } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES_OLD)) {
+                               _cellHasNote = true;
+                       } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) {
+                               _cellHasNote = true;
+                       }
+               }
+
+               public void endDocument() {
+                       // do nothing
+               }
+               public void endPrefixMapping(String prefix) {
+                       // do nothing
+               }
+               public void ignorableWhitespace(char[] ch, int start, int length) {
+                       // do nothing
+               }
+               public void processingInstruction(String target, String data) {
+                       // do nothing
+               }
+               public void setDocumentLocator(Locator locator) {
+                       // do nothing
+               }
+               public void skippedEntity(String name) {
+                       // do nothing
+               }
+               public void startDocument() {
+                       // do nothing
+               }
+               public void startPrefixMapping(String prefix, String uri) {
+                       // do nothing
+               }
+       }
+
+       private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) {
+               XMLReader xr;
+
+               try {
+                       // First up, try the default one
+                       xr = XMLReaderFactory.createXMLReader();
+               } catch (SAXException e) {
+                       // Try one for java 1.4
+                       System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
+                       try {
+                               xr = XMLReaderFactory.createXMLReader();
+                       } catch (SAXException e2) {
+                               throw new RuntimeException(e2);
+                       }
+               }
+               xr.setContentHandler(new EFFDocHandler(fdc));
+
+               InputSource inSrc = new InputSource(is);
+
+               try {
+                       xr.parse(inSrc);
+                       is.close();
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               } catch (SAXException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+       /**
+        * To be sure that no tricky unicode chars make it through to the output file.
+        */
+       private static final class SimpleAsciiOutputStream extends OutputStream {
+
+               private final OutputStream _os;
+
+               public SimpleAsciiOutputStream(OutputStream os) {
+                       _os = os;
+               }
+               public void write(int b) throws IOException {
+                       checkByte(b);
+                       _os.write(b);
+               }
+               private static void checkByte(int b) {
+                       if (!isSimpleAscii((char)b)) {
+                               throw new RuntimeException("Encountered char (" + b + ") which was not simple ascii as expected");
+                       }
+               }
+               public void write(byte[] b, int off, int len) throws IOException {
+                       for (int i = 0; i < len; i++) {
+                               checkByte(b[i + off]);
+
+                       }
+                       _os.write(b, off, len);
+               }
+       }
+
+       private static void processFile(File effDocFile, File outFile) {
+               if(!effDocFile.exists()) {
+                       throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
+               }
+               OutputStream os;
+               try {
+                       os = new FileOutputStream(outFile);
+               } catch (FileNotFoundException e) {
+                       throw new RuntimeException(e);
+               }
+               os = new SimpleAsciiOutputStream(os);
+               PrintStream ps;
+               try {
+                       ps = new PrintStream(os, true, "UTF-8");
+               } catch(UnsupportedEncodingException e) {
+                       throw new RuntimeException(e);
+               }
+
+               outputLicenseHeader(ps);
+               Class genClass = ExcelFileFormatDocFunctionExtractor.class;
+               ps.println("# Created by (" + genClass.getName() + ")");
+               // identify the source file
+               ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'");
+               ps.println(" (size=" + effDocFile.length() + ", md5=" + getFileMD5(effDocFile) + ")");
+               ps.println("#");
+               ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )");
+               ps.println("");
+               try {
+                       ZipFile zf = new ZipFile(effDocFile);
+                       InputStream is = zf.getInputStream(zf.getEntry("content.xml"));
+                       extractFunctionData(new FunctionDataCollector(ps), is);
+                       zf.close();
+               } catch (ZipException e) {
+                       throw new RuntimeException(e);
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+               ps.close();
+
+               String canonicalOutputFileName;
+               try {
+                       canonicalOutputFileName = outFile.getCanonicalPath();
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+               System.out.println("Successfully output to '" + canonicalOutputFileName + "'");
+       }
+
+       private static void outputLicenseHeader(PrintStream ps) {
+               String[] lines= {
+                       "Licensed to the Apache Software Foundation (ASF) under one or more",
+                       "contributor license agreements.  See the NOTICE file distributed with",
+                       "this work for additional information regarding copyright ownership.",
+                       "The ASF licenses this file to You 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.",
+               };
+               for (int i = 0; i < lines.length; i++) {
+                       ps.print("# ");
+                       ps.println(lines[i]);
+               }
+               ps.println();
+       }
+
+       /**
+        * Helps identify the source file
+        */
+       private static String getFileMD5(File f) {
+               MessageDigest m;
+               try {
+                       m = MessageDigest.getInstance("MD5");
+               } catch (NoSuchAlgorithmException e) {
+                       throw new RuntimeException(e);
+               }
+
+               byte[]buf = new byte[2048];
+               try {
+                       InputStream is = new FileInputStream(f);
+                       while(true) {
+                               int bytesRead = is.read(buf);
+                               if(bytesRead<1) {
+                                       break;
+                               }
+                               m.update(buf, 0, bytesRead);
+                       }
+                       is.close();
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+
+               return "0x" + new BigInteger(1, m.digest()).toString(16);
+       }
+
+       private static File downloadSourceFile() {
+               URL url;
+               try {
+                       url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME);
+               } catch (MalformedURLException e) {
+                       throw new RuntimeException(e);
+               }
+
+               File result;
+               byte[]buf = new byte[2048];
+               try {
+                       URLConnection conn = url.openConnection();
+                       InputStream is = conn.getInputStream();
+                       System.out.println("downloading " + url.toExternalForm());
+                       result = File.createTempFile("excelfileformat", ".odt");
+                       OutputStream os = new FileOutputStream(result);
+                       while(true) {
+                               int bytesRead = is.read(buf);
+                               if(bytesRead<1) {
+                                       break;
+                               }
+                               os.write(buf, 0, bytesRead);
+                       }
+                       is.close();
+                       os.close();
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
+               System.out.println("file downloaded ok");
+               return result;
+       }
+
+       public static void main(String[] args) {
+
+               File outFile = new File("functionMetadata-asGenerated.txt");
+
+               if (false) { // set true to use local file
+                       File dir = new File("c:/temp");
+                       File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
+                       processFile(effDocFile, outFile);
+                       return;
+               }
+
+               File tempEFFDocFile = downloadSourceFile();
+               processFile(tempEFFDocFile, outFile);
+               tempEFFDocFile.delete();
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java b/src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java
new file mode 100644 (file)
index 0000000..b050401
--- /dev/null
@@ -0,0 +1,44 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.function;
+
+import junit.framework.TestCase;
+
+/**
+ * 
+ * @author Josh Micich
+ */
+public final class TestFunctionMetadataRegistry extends TestCase {
+
+       public void testWellKnownFunctions() {
+               confirmFunction(0, "COUNT");
+               confirmFunction(1, "IF");
+
+       }
+
+       private static void confirmFunction(int index, String funcName) {
+               FunctionMetadata fm;
+               fm = FunctionMetadataRegistry.getFunctionByIndex(index);
+               assertNotNull(fm);
+               assertEquals(funcName, fm.getName());
+
+               fm = FunctionMetadataRegistry.getFunctionByName(funcName);
+               assertNotNull(fm);
+               assertEquals(index, fm.getIndex());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java
new file mode 100644 (file)
index 0000000..a6872e5
--- /dev/null
@@ -0,0 +1,90 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.function;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
+import org.apache.poi.hssf.record.formula.FuncPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+/**
+ * Tests parsing of some built-in functions that were not properly
+ * registered in POI as of bug #44675, #44733 (March/April 2008).
+ * 
+ * @author Josh Micich
+ */
+public final class TestParseMissingBuiltInFuncs extends TestCase {
+
+       private static Ptg[] parse(String formula) {
+               HSSFWorkbook book = new HSSFWorkbook();
+               return HSSFFormulaParser.parse(formula, book);
+       }
+       private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) {
+               Ptg[] ptgs = parse(formula);
+               Ptg ptgF = ptgs[ptgs.length-1];  // func is last RPN token in all these formulas
+               
+               // Check critical things in the Ptg array encoding.
+               if(!(ptgF instanceof AbstractFunctionPtg)) {
+                   throw new RuntimeException("function token missing");
+               }
+               AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
+               if(func.getFunctionIndex() == 255) {
+                       throw new AssertionFailedError("Failed to recognise built-in function in formula '" 
+                                       + formula + "'");
+               }
+               assertEquals(expPtgArraySize, ptgs.length);
+               assertEquals(funcIx, func.getFunctionIndex());
+               Class expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class;
+               assertEquals(expCls, ptgF.getClass());
+               
+               // check that parsed Ptg array converts back to formula text OK
+               HSSFWorkbook book = new HSSFWorkbook();
+               String reRenderedFormula = HSSFFormulaParser.toFormulaString(book, ptgs);
+               assertEquals(formula, reRenderedFormula);
+       }
+       
+       public void testDatedif() {
+               int expSize = 4;   // NB would be 5 if POI added tAttrVolatile properly
+               confirmFunc("DATEDIF(NOW(),NOW(),\"d\")", expSize, false, 351);
+       }
+
+       public void testDdb() {
+               confirmFunc("DDB(1,1,1,1,1)", 6, true, 144);
+       }
+       public void testAtan() {
+               confirmFunc("ATAN(1)", 2, false, 18);
+       }
+       
+       public void testUsdollar() {
+               confirmFunc("USDOLLAR(1)", 2, true, 204);
+       }
+
+       public void testDBCS() {
+               confirmFunc("DBCS(\"abc\")", 2, false, 215);
+       }
+       public void testIsnontext() {
+               confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190);
+       }
+       public void testDproduct() {
+               confirmFunc("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", 4, false, 189);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java
new file mode 100644 (file)
index 0000000..9de7e76
--- /dev/null
@@ -0,0 +1,162 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.function;
+
+import java.lang.reflect.InvocationTargetException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.RecordFormatException;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+/**
+ * Tests reading from a sample spreadsheet some built-in functions that were not properly
+ * registered in POI as of bug #44675, #44733 (March/April 2008).
+ * 
+ * @author Josh Micich
+ */
+public final class TestReadMissingBuiltInFuncs extends TestCase {
+
+       /**
+        * This spreadsheet has examples of calls to the interesting built-in functions in cells A1:A7
+        */
+       private static final String SAMPLE_SPREADSHEET_FILE_NAME = "missingFuncs44675.xls";
+       private static HSSFSheet _sheet;
+
+       private static HSSFSheet getSheet() {
+               if (_sheet == null) {
+                       HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_SPREADSHEET_FILE_NAME);
+                       _sheet = wb.getSheetAt(0);
+               }
+               return _sheet;
+       }
+
+       public void testDatedif() {
+               
+               String formula;
+               try {
+                       formula = getCellFormula(0);
+               } catch (IllegalStateException e) {
+                       if(e.getMessage().startsWith("Too few arguments")) {
+                               if(e.getMessage().indexOf("AttrPtg") > 0) {
+                                       throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
+                               }
+                               throw afe("NOW() registered with 1 arg instead of 0");
+                       }
+                       if(e.getMessage().startsWith("too much stuff")) {
+                               throw afe("DATEDIF() not registered");
+                       }
+                       // some other unexpected error
+                       throw e;
+               }
+               assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
+       }
+       public void testDdb() {
+
+               String formula = getCellFormula(1);
+               if("externalflag(1,1,1,1,1)".equals(formula)) {
+                       throw afe("DDB() not registered");
+               }
+               assertEquals("DDB(1,1,1,1,1)", formula);
+       }
+       public void testAtan() {
+
+               String formula = getCellFormula(2);
+               if(formula.equals("ARCTAN(1)")) {
+                       throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
+               }
+               assertEquals("ATAN(1)", formula);
+       }
+
+       public void testUsdollar() {
+       
+               String formula = getCellFormula(3);
+               if(formula.equals("YEN(1)")) {
+                       throw afe("func ix 204 registered as YEN() instead of USDOLLAR()");
+               }
+               assertEquals("USDOLLAR(1)", formula);
+       }
+
+       public void testDBCS() {
+       
+               String formula;
+               try {
+                       formula = getCellFormula(4);
+               } catch (IllegalStateException e) {
+                       if(e.getMessage().startsWith("too much stuff")) {
+                               throw afe("DBCS() not registered");
+                       }
+                       // some other unexpected error
+                       throw e;
+               } catch (NegativeArraySizeException e) {
+                       throw afe("found err- DBCS() registered with -1 args");
+               }
+               if(formula.equals("JIS(\"abc\")")) {
+                       throw afe("func ix 215 registered as JIS() instead of DBCS()");
+               }
+               assertEquals("DBCS(\"abc\")", formula);
+       }
+       public void testIsnontext() {
+               
+               String formula;
+               try {
+                       formula = getCellFormula(5);
+               } catch (IllegalStateException e) {
+                       if(e.getMessage().startsWith("too much stuff")) {
+                               throw afe("ISNONTEXT() registered with wrong index");
+                       }
+                       // some other unexpected error
+                       throw e;
+               }
+               assertEquals("ISNONTEXT(\"abc\")", formula);
+       }
+       public void testDproduct() {
+               
+               String formula = getCellFormula(6);
+               assertEquals("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", formula);
+       }
+
+       private String getCellFormula(int rowIx) {
+               HSSFSheet sheet;
+               try {
+                       sheet = getSheet();
+               } catch (RecordFormatException e) {
+                       if(e.getCause() instanceof InvocationTargetException) {
+                               InvocationTargetException ite = (InvocationTargetException) e.getCause();
+                               if(ite.getTargetException() instanceof RuntimeException) {
+                                       RuntimeException re = (RuntimeException) ite.getTargetException();
+                                       if(re.getMessage().equals("Invalid built-in function index (189)")) {
+                                               throw afe("DPRODUCT() registered with wrong index");
+                                       }
+                               }
+                       }
+                       // some other unexpected error
+                       throw e;
+               }
+               String result = sheet.getRow(rowIx).getCell(0).getCellFormula();
+               if (false) {
+                       System.err.println(result);
+               }
+               return result;
+       }
+       private static AssertionFailedError afe(String msg) {
+               return new AssertionFailedError(msg);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/AbstractNumericTestCase.java b/src/testcases/org/apache/poi/ss/formula/functions/AbstractNumericTestCase.java
new file mode 100644 (file)
index 0000000..c5453ea
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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.
+*/
+/*
+ * Created on May 29, 2005
+ *
+ */
+package org.apache.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ *
+ */
+public abstract class AbstractNumericTestCase extends TestCase {
+
+    public static final double POS_ZERO = 1E-4;
+    public static final double DIFF_TOLERANCE_FACTOR = 1E-8;
+
+    public void setUp() {
+    }
+
+    public void tearDown() {
+    }
+
+    /**
+     * Why doesnt JUnit have a method like this for doubles? 
+     * The current impl (3.8.1) of Junit has a retar*** method
+     * for comparing doubles. DO NOT use that.
+     * TODO: This class should really be in an abstract super class
+     * to avoid code duplication across this project.
+     * @param message
+     * @param baseval
+     * @param checkval
+     */
+    public static void assertEquals(String message, double baseval, double checkval, double almostZero, double diffToleranceFactor) {
+        double posZero = Math.abs(almostZero);
+        double negZero = -1 * posZero;
+        if (Double.isNaN(baseval)) {
+            assertTrue(message+": Expected " + baseval + " but was " + checkval
+                    , Double.isNaN(baseval));
+        }
+        else if (Double.isInfinite(baseval)) {
+            assertTrue(message+": Expected " + baseval + " but was " + checkval
+                    , Double.isInfinite(baseval) && ((baseval<0) == (checkval<0)));
+        }
+        else {
+            assertTrue(message+": Expected " + baseval + " but was " + checkval
+                ,baseval != 0
+                    ? Math.abs(baseval - checkval) <= Math.abs(diffToleranceFactor * baseval)
+                    : checkval < posZero && checkval > negZero);
+        }
+    }
+
+    public static void assertEquals(String msg, double baseval, double checkval) {
+        assertEquals(msg, baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
+    }
+
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/AllIndividualFunctionEvaluationTests.java b/src/testcases/org/apache/poi/ss/formula/functions/AllIndividualFunctionEvaluationTests.java
new file mode 100644 (file)
index 0000000..4e42389
--- /dev/null
@@ -0,0 +1,65 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Direct tests for all implementors of <code>Function</code>.
+ *
+ * @author Josh Micich
+ */
+public final class AllIndividualFunctionEvaluationTests {
+
+       public static Test suite() {
+               TestSuite result = new TestSuite(AllIndividualFunctionEvaluationTests.class.getName());
+               result.addTestSuite(TestAverage.class);
+               result.addTestSuite(TestCountFuncs.class);
+               result.addTestSuite(TestDate.class);
+               result.addTestSuite(TestDays360.class);
+               result.addTestSuite(TestFinanceLib.class);
+               result.addTestSuite(TestFind.class);
+               result.addTestSuite(TestIndex.class);
+               result.addTestSuite(TestIndexFunctionFromSpreadsheet.class);
+               result.addTestSuite(TestIndirect.class);
+               result.addTestSuite(TestIsBlank.class);
+               result.addTestSuite(TestLen.class);
+               result.addTestSuite(TestLookupFunctionsFromSpreadsheet.class);
+               result.addTestSuite(TestMatch.class);
+               result.addTestSuite(TestMathX.class);
+               result.addTestSuite(TestMid.class);
+               result.addTestSuite(TestNper.class);
+               result.addTestSuite(TestOffset.class);
+               result.addTestSuite(TestPmt.class);
+               result.addTestSuite(TestRoundFuncs.class);
+               result.addTestSuite(TestRowCol.class);
+               result.addTestSuite(TestStatsLib.class);
+               result.addTestSuite(TestSubtotal.class);
+               result.addTestSuite(TestSumif.class);
+               result.addTestSuite(TestSumproduct.class);
+               result.addTestSuite(TestText.class);
+               result.addTestSuite(TestTFunc.class);
+               result.addTestSuite(TestTime.class);
+               result.addTestSuite(TestTrim.class);
+               result.addTestSuite(TestTrunc.class);
+               result.addTestSuite(TestValue.class);
+               result.addTestSuite(TestXYNumericFunction.class);
+               return result;
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/EvalFactory.java b/src/testcases/org/apache/poi/ss/formula/functions/EvalFactory.java
new file mode 100644 (file)
index 0000000..7eee562
--- /dev/null
@@ -0,0 +1,174 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import org.apache.poi.hssf.record.formula.AreaI;
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.hssf.record.formula.Ref3DPtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.AreaEvalBase;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.RefEval;
+import org.apache.poi.ss.formula.eval.RefEvalBase;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.TwoDEval;
+
+/**
+ * Test helper class for creating mock <code>Eval</code> objects
+ *
+ * @author Josh Micich
+ */
+public final class EvalFactory {
+
+       private EvalFactory() {
+               // no instances of this class
+       }
+
+       /**
+        * Creates a dummy AreaEval
+        * @param values empty (<code>null</code>) entries in this array will be converted to NumberEval.ZERO
+        */
+       public static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) {
+               AreaPtg areaPtg = new AreaPtg(areaRefStr);
+               return createAreaEval(areaPtg, values);
+       }
+
+       /**
+        * Creates a dummy AreaEval
+        * @param values empty (<code>null</code>) entries in this array will be converted to NumberEval.ZERO
+        */
+       public static AreaEval createAreaEval(AreaPtg areaPtg, ValueEval[] values) {
+               int nCols = areaPtg.getLastColumn() - areaPtg.getFirstColumn() + 1;
+               int nRows = areaPtg.getLastRow() - areaPtg.getFirstRow() + 1;
+               int nExpected = nRows * nCols;
+               if (values.length != nExpected) {
+                       throw new RuntimeException("Expected " + nExpected + " values but got " + values.length);
+               }
+               for (int i = 0; i < nExpected; i++) {
+                       if (values[i] == null) {
+                               values[i] = NumberEval.ZERO;
+                       }
+               }
+               return new MockAreaEval(areaPtg, values);
+       }
+
+       /**
+        * Creates a single RefEval (with value zero)
+        */
+       public static RefEval createRefEval(String refStr) {
+               return createRefEval(refStr, NumberEval.ZERO);
+       }
+       public static RefEval createRefEval(String refStr, ValueEval value) {
+               return new MockRefEval(new RefPtg(refStr), value);
+       }
+
+       private static final class MockAreaEval extends AreaEvalBase {
+               private final ValueEval[] _values;
+               public MockAreaEval(AreaI areaPtg, ValueEval[] values) {
+                       super(areaPtg);
+                       _values = values;
+               }
+               private MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn, ValueEval[] values) {
+                       super(firstRow, firstColumn, lastRow, lastColumn);
+                       _values = values;
+               }
+               public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
+                       if (relativeRowIndex < 0 || relativeRowIndex >=getHeight()) {
+                               throw new IllegalArgumentException("row index out of range");
+                       }
+                       int width = getWidth();
+                       if (relativeColumnIndex < 0 || relativeColumnIndex >=width) {
+                               throw new IllegalArgumentException("column index out of range");
+                       }
+                       int oneDimensionalIndex = relativeRowIndex * width + relativeColumnIndex;
+                       return _values[oneDimensionalIndex];
+               }
+               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
+                       if (relFirstRowIx < 0 || relFirstColIx < 0
+                                       || relLastRowIx >= getHeight() || relLastColIx >= getWidth()) {
+                               throw new RuntimeException("Operation not implemented on this mock object");
+                       }
+
+                       if (relFirstRowIx == 0 && relFirstColIx == 0
+                                       && relLastRowIx == getHeight()-1 && relLastColIx == getWidth()-1) {
+                               return this;
+                       }
+                       ValueEval[] values = transpose(_values, getWidth(), relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+                       return new MockAreaEval(getFirstRow() + relFirstRowIx, getFirstColumn() + relFirstColIx,
+                                       getFirstRow() + relLastRowIx, getFirstColumn() + relLastColIx, values);
+               }
+               private static ValueEval[] transpose(ValueEval[] srcValues, int srcWidth,
+                               int relFirstRowIx, int relLastRowIx,
+                               int relFirstColIx, int relLastColIx) {
+                       int height = relLastRowIx - relFirstRowIx + 1;
+                       int width = relLastColIx - relFirstColIx + 1;
+                       ValueEval[] result = new ValueEval[height * width];
+                       for (int r=0; r<height; r++) {
+                               int srcRowIx = r + relFirstRowIx;
+                               for (int c=0; c<width; c++) {
+                                       int srcColIx = c + relFirstColIx;
+                                       int destIx = r * width + c;
+                                       int srcIx = srcRowIx * srcWidth + srcColIx;
+                                       result[destIx] = srcValues[srcIx];
+                               }
+                       }
+                       return result;
+               }
+               public TwoDEval getRow(int rowIndex) {
+                       if (rowIndex >= getHeight()) {
+                               throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+                                               + ".  Allowable range is (0.." + getHeight() + ").");
+                       }
+                       ValueEval[] values = new ValueEval[getWidth()];
+                       for (int i = 0; i < values.length; i++) {
+                               values[i] = getRelativeValue(rowIndex, i);
+                       }
+                       return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn(), values);
+               }
+               public TwoDEval getColumn(int columnIndex) {
+                       if (columnIndex >= getWidth()) {
+                               throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
+                                               + ".  Allowable range is (0.." + getWidth() + ").");
+                       }
+                       ValueEval[] values = new ValueEval[getHeight()];
+                       for (int i = 0; i < values.length; i++) {
+                               values[i] = getRelativeValue(i, columnIndex);
+                       }
+                       return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex, values);
+               }
+       }
+
+       private static final class MockRefEval extends RefEvalBase {
+               private final ValueEval _value;
+               public MockRefEval(RefPtg ptg, ValueEval value) {
+                       super(ptg.getRow(), ptg.getColumn());
+                       _value = value;
+               }
+               public MockRefEval(Ref3DPtg ptg, ValueEval value) {
+                       super(ptg.getRow(), ptg.getColumn());
+                       _value = value;
+               }
+               public ValueEval getInnerValueEval() {
+                       return _value;
+               }
+               public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
+                       throw new RuntimeException("Operation not implemented on this mock object");
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/NumericFunctionInvoker.java b/src/testcases/org/apache/poi/ss/formula/functions/NumericFunctionInvoker.java
new file mode 100644 (file)
index 0000000..f51e8a2
--- /dev/null
@@ -0,0 +1,111 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumericValueEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+
+/**
+ * Test helper class for invoking functions with numeric results.
+ *
+ * @author Josh Micich
+ */
+public final class NumericFunctionInvoker {
+
+       private NumericFunctionInvoker() {
+               // no instances of this class
+       }
+
+       private static final class NumericEvalEx extends Exception {
+               public NumericEvalEx(String msg) {
+                       super(msg);
+               }
+       }
+
+       /**
+        * Invokes the specified function with the arguments.
+        * <p/>
+        * Assumes that the cell coordinate parameters of
+        *  <code>Function.evaluate(args, srcCellRow, srcCellCol)</code>
+        * are not required.
+        * <p/>
+        * This method cannot be used for confirming error return codes.  Any non-numeric evaluation
+        * result causes the current junit test to fail.
+        */
+       public static double invoke(Function f, ValueEval[] args) {
+               return invoke(f, args, -1, -1);
+       }
+       /**
+        * Invokes the specified operator with the arguments.
+        * <p/>
+        * This method cannot be used for confirming error return codes.  Any non-numeric evaluation
+        * result causes the current junit test to fail.
+        */
+       public static double invoke(Function f, ValueEval[] args, int srcCellRow, int srcCellCol) {
+               try {
+                       return invokeInternal(f, args, srcCellRow, srcCellCol);
+               } catch (NumericEvalEx e) {
+                       throw new AssertionFailedError("Evaluation of function (" + f.getClass().getName()
+                                       + ") failed: " + e.getMessage());
+               }
+       }
+       /**
+        * Formats nicer error messages for the junit output
+        */
+       private static double invokeInternal(Function target, ValueEval[] args, int srcCellRow, int srcCellCol)
+                               throws NumericEvalEx {
+               ValueEval evalResult;
+               try {
+                       evalResult = target.evaluate(args, srcCellRow, (short)srcCellCol);
+               } catch (NotImplementedException e) {
+                       throw new NumericEvalEx("Not implemented:" + e.getMessage());
+               }
+
+               if(evalResult == null) {
+                       throw new NumericEvalEx("Result object was null");
+               }
+               if(evalResult instanceof ErrorEval) {
+                       ErrorEval ee = (ErrorEval) evalResult;
+                       throw new NumericEvalEx(formatErrorMessage(ee));
+               }
+               if(!(evalResult instanceof NumericValueEval)) {
+                       throw new NumericEvalEx("Result object type (" + evalResult.getClass().getName()
+                                       + ") is invalid.  Expected implementor of ("
+                                       + NumericValueEval.class.getName() + ")");
+               }
+
+               NumericValueEval result = (NumericValueEval) evalResult;
+               return result.getNumberValue();
+       }
+       private static String formatErrorMessage(ErrorEval ee) {
+               if(errorCodesAreEqual(ee, ErrorEval.VALUE_INVALID)) {
+                       return "Error code: #VALUE! (invalid value)";
+               }
+               return "Error code=" + ee.getErrorCode();
+       }
+       private static boolean errorCodesAreEqual(ErrorEval a, ErrorEval b) {
+               if(a==b) {
+                       return true;
+               }
+               return a.getErrorCode() == b.getErrorCode();
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestAverage.java b/src/testcases/org/apache/poi/ss/formula/functions/TestAverage.java
new file mode 100644 (file)
index 0000000..1dcba00
--- /dev/null
@@ -0,0 +1,98 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+/**
+ * Tests for Excel function AVERAGE()
+ *
+ * @author Josh Micich
+ */
+public final class TestAverage extends TestCase {
+
+       private static ValueEval invokeAverage(ValueEval[] args) {
+               return AggregateFunction.AVERAGE.evaluate(args, -1, (short)-1);
+       }
+
+       private void confirmAverage(ValueEval[] args, double expected) {
+               ValueEval result = invokeAverage(args);
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
+       }
+
+       private void confirmAverage(ValueEval[] args, ErrorEval expectedError) {
+               ValueEval result = invokeAverage(args);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
+       }
+
+       public void testBasic() {
+
+               ValueEval[] values = {
+                               new NumberEval(1),
+                               new NumberEval(2),
+                               new NumberEval(3),
+                               new NumberEval(4),
+               };
+
+               confirmAverage(values, 2.5);
+
+               values = new ValueEval[] {
+                               new NumberEval(1),
+                               new NumberEval(2),
+                               BlankEval.instance,
+                               new NumberEval(3),
+                               BlankEval.instance,
+                               new NumberEval(4),
+                               BlankEval.instance,
+               };
+
+               confirmAverage(values, 2.5);
+       }
+
+       /**
+        * Valid cases where values are not pure numbers
+        */
+       public void testUnusualArgs() {
+               ValueEval[] values = {
+                               new NumberEval(1),
+                               new NumberEval(2),
+                               BoolEval.TRUE,
+                               BoolEval.FALSE,
+               };
+
+               confirmAverage(values, 1.0);
+
+       }
+
+       public void testErrors() {
+               ValueEval[] values = {
+                               new NumberEval(1),
+                               ErrorEval.NAME_INVALID,
+                               new NumberEval(3),
+                               ErrorEval.DIV_ZERO,
+               };
+               confirmAverage(values, ErrorEval.NAME_INVALID);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java b/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java
new file mode 100644 (file)
index 0000000..8897feb
--- /dev/null
@@ -0,0 +1,460 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.OperandResolver;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.CountUtils.I_MatchPredicate;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Test cases for COUNT(), COUNTA() COUNTIF(), COUNTBLANK()
+ *
+ * @author Josh Micich
+ */
+public final class TestCountFuncs extends TestCase {
+
+       private static final String NULL = null;
+
+       public void testCountBlank() {
+
+               AreaEval range;
+               ValueEval[] values;
+
+               values = new ValueEval[] {
+                               new NumberEval(0),
+                               new StringEval(""),     // note - does not match blank
+                               BoolEval.TRUE,
+                               BoolEval.FALSE,
+                               ErrorEval.DIV_ZERO,
+                               BlankEval.instance,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountBlank(1, range);
+
+               values = new ValueEval[] {
+                               new NumberEval(0),
+                               new StringEval(""),     // note - does not match blank
+                               BlankEval.instance,
+                               BoolEval.FALSE,
+                               BoolEval.TRUE,
+                               BlankEval.instance,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountBlank(2, range);
+       }
+
+       public void testCountA() {
+
+               ValueEval[] args;
+
+               args = new ValueEval[] {
+                       new NumberEval(0),
+               };
+               confirmCountA(1, args);
+
+               args = new ValueEval[] {
+                       new NumberEval(0),
+                       new NumberEval(0),
+                       new StringEval(""),
+               };
+               confirmCountA(3, args);
+
+               args = new ValueEval[] {
+                       EvalFactory.createAreaEval("D2:F5", new ValueEval[12]),
+               };
+               confirmCountA(12, args);
+
+               args = new ValueEval[] {
+                       EvalFactory.createAreaEval("D1:F5", new ValueEval[15]),
+                       EvalFactory.createRefEval("A1"),
+                       EvalFactory.createAreaEval("A1:G6", new ValueEval[42]),
+                       new NumberEval(0),
+               };
+               confirmCountA(59, args);
+       }
+
+       public void testCountIf() {
+
+               AreaEval range;
+               ValueEval[] values;
+
+               // when criteria is a boolean value
+               values = new ValueEval[] {
+                               new NumberEval(0),
+                               new StringEval("TRUE"), // note - does not match boolean TRUE
+                               BoolEval.TRUE,
+                               BoolEval.FALSE,
+                               BoolEval.TRUE,
+                               BlankEval.instance,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountIf(2, range, BoolEval.TRUE);
+
+               // when criteria is numeric
+               values = new ValueEval[] {
+                               new NumberEval(0),
+                               new StringEval("2"),
+                               new StringEval("2.001"),
+                               new NumberEval(2),
+                               new NumberEval(2),
+                               BoolEval.TRUE,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountIf(3, range, new NumberEval(2));
+               // note - same results when criteria is a string that parses as the number with the same value
+               confirmCountIf(3, range, new StringEval("2.00"));
+
+               // when criteria is an expression (starting with a comparison operator)
+               confirmCountIf(2, range, new StringEval(">1"));
+               // when criteria is an expression (starting with a comparison operator)
+               confirmCountIf(2, range, new StringEval(">0.5"));
+       }
+
+       public void testCriteriaPredicateNe_Bug46647() {
+               I_MatchPredicate mp = Countif.createCriteriaPredicate(new StringEval("<>aa"), 0, 0);
+               StringEval seA = new StringEval("aa"); // this should not match the criteria '<>aa'
+               StringEval seB = new StringEval("bb"); // this should match
+               if (mp.matches(seA) && !mp.matches(seB)) {
+                       throw new AssertionFailedError("Identified bug 46647");
+               }
+               assertFalse(mp.matches(seA));
+               assertTrue(mp.matches(seB));
+
+               // general tests for not-equal (<>) operator
+               AreaEval range;
+               ValueEval[] values;
+
+               values = new ValueEval[] {
+                               new StringEval("aa"),
+                               new StringEval("def"),
+                               new StringEval("aa"),
+                               new StringEval("ghi"),
+                               new StringEval("aa"),
+                               new StringEval("aa"),
+               };
+
+               range = EvalFactory.createAreaEval("A1:A6", values);
+               confirmCountIf(2, range, new StringEval("<>aa"));
+
+               values = new ValueEval[] {
+                               new StringEval("ab"),
+                               new StringEval("aabb"),
+                               new StringEval("aa"), // match
+                               new StringEval("abb"),
+                               new StringEval("aab"),
+                               new StringEval("ba"), // match
+               };
+
+               range = EvalFactory.createAreaEval("A1:A6", values);
+               confirmCountIf(2, range, new StringEval("<>a*b"));
+
+
+               values = new ValueEval[] {
+                               new NumberEval(222),
+                               new NumberEval(222),
+                               new NumberEval(111),
+                               new StringEval("aa"),
+                               new StringEval("111"),
+               };
+
+               range = EvalFactory.createAreaEval("A1:A5", values);
+               confirmCountIf(4, range, new StringEval("<>111"));
+       }
+
+       /**
+        * special case where the criteria argument is a cell reference
+        */
+       public void testCountIfWithCriteriaReference() {
+
+               ValueEval[] values = {
+                               new NumberEval(22),
+                               new NumberEval(25),
+                               new NumberEval(21),
+                               new NumberEval(25),
+                               new NumberEval(25),
+                               new NumberEval(25),
+               };
+               AreaEval arg0 = EvalFactory.createAreaEval("C1:C6", values);
+
+               ValueEval criteriaArg = EvalFactory.createRefEval("A1", new NumberEval(25));
+               ValueEval[] args=  { arg0, criteriaArg, };
+
+               double actual = NumericFunctionInvoker.invoke(new Countif(), args);
+               assertEquals(4, actual, 0D);
+       }
+
+       private static void confirmCountA(int expected, ValueEval[] args) {
+               double result = NumericFunctionInvoker.invoke(new Counta(), args);
+               assertEquals(expected, result, 0);
+       }
+       private static void confirmCountIf(int expected, AreaEval range, ValueEval criteria) {
+
+               ValueEval[] args = { range, criteria, };
+               double result = NumericFunctionInvoker.invoke(new Countif(), args);
+               assertEquals(expected, result, 0);
+       }
+       private static void confirmCountBlank(int expected, AreaEval range) {
+
+               ValueEval[] args = { range };
+               double result = NumericFunctionInvoker.invoke(new Countblank(), args);
+               assertEquals(expected, result, 0);
+       }
+
+       private static I_MatchPredicate createCriteriaPredicate(ValueEval ev) {
+               return Countif.createCriteriaPredicate(ev, 0, 0);
+       }
+
+       /**
+        * the criteria arg is mostly handled by {@link OperandResolver#getSingleValue(org.apache.poi.ss.formula.eval.ValueEval, int, int)}}
+        */
+       public void testCountifAreaCriteria() {
+               int srcColIx = 2; // anything but column A
+
+               ValueEval v0 = new NumberEval(2.0);
+               ValueEval v1 = new StringEval("abc");
+               ValueEval v2 = ErrorEval.DIV_ZERO;
+
+               AreaEval ev = EvalFactory.createAreaEval("A10:A12", new ValueEval[] { v0, v1, v2, });
+
+               I_MatchPredicate mp;
+               mp = Countif.createCriteriaPredicate(ev, 9, srcColIx);
+               confirmPredicate(true, mp, srcColIx);
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
+
+               mp = Countif.createCriteriaPredicate(ev, 10, srcColIx);
+               confirmPredicate(false, mp, srcColIx);
+               confirmPredicate(true, mp, "abc");
+               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
+
+               mp = Countif.createCriteriaPredicate(ev, 11, srcColIx);
+               confirmPredicate(false, mp, srcColIx);
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(true, mp, ErrorEval.DIV_ZERO);
+               confirmPredicate(false, mp, ErrorEval.VALUE_INVALID);
+
+               // tricky: indexing outside of A10:A12
+               // even this #VALUE! error gets used by COUNTIF as valid criteria
+               mp = Countif.createCriteriaPredicate(ev, 12, srcColIx);
+               confirmPredicate(false, mp, srcColIx);
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
+               confirmPredicate(true, mp, ErrorEval.VALUE_INVALID);
+       }
+
+       public void testCountifEmptyStringCriteria() {
+               I_MatchPredicate mp;
+
+               // pred '=' matches blank cell but not empty string
+               mp = createCriteriaPredicate(new StringEval("="));
+               confirmPredicate(false, mp, "");
+               confirmPredicate(true, mp, NULL);
+
+               // pred '' matches both blank cell but not empty string
+               mp = createCriteriaPredicate(new StringEval(""));
+               confirmPredicate(true, mp, "");
+               confirmPredicate(true, mp, NULL);
+
+               // pred '<>' matches empty string but not blank cell
+               mp = createCriteriaPredicate(new StringEval("<>"));
+               confirmPredicate(false, mp, NULL);
+               confirmPredicate(true, mp, "");
+       }
+
+       public void testCountifComparisons() {
+               I_MatchPredicate mp;
+
+               mp = createCriteriaPredicate(new StringEval(">5"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(false, mp, 5);
+               confirmPredicate(true, mp, 6);
+
+               mp = createCriteriaPredicate(new StringEval("<=5"));
+               confirmPredicate(true, mp, 4);
+               confirmPredicate(true, mp, 5);
+               confirmPredicate(false, mp, 6);
+               confirmPredicate(false, mp, "4.9");
+               confirmPredicate(false, mp, "4.9t");
+               confirmPredicate(false, mp, "5.1");
+               confirmPredicate(false, mp, NULL);
+
+               mp = createCriteriaPredicate(new StringEval("=abc"));
+               confirmPredicate(true, mp, "abc");
+
+               mp = createCriteriaPredicate(new StringEval("=42"));
+               confirmPredicate(false, mp, 41);
+               confirmPredicate(true, mp, 42);
+               confirmPredicate(true, mp, "42");
+
+               mp = createCriteriaPredicate(new StringEval(">abc"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(true, mp, "abd");
+
+               mp = createCriteriaPredicate(new StringEval(">4t3"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(false, mp, 500);
+               confirmPredicate(true, mp, "500");
+               confirmPredicate(true, mp, "4t4");
+       }
+
+       /**
+        * the criteria arg value can be an error code (the error does not
+        * propagate to the COUNTIF result).
+        */
+       public void testCountifErrorCriteria() {
+               I_MatchPredicate mp;
+
+               mp = createCriteriaPredicate(new StringEval("#REF!"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(false, mp, "#REF!");
+               confirmPredicate(true, mp, ErrorEval.REF_INVALID);
+
+               mp = createCriteriaPredicate(new StringEval("<#VALUE!"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(false, mp, "#DIV/0!");
+               confirmPredicate(false, mp, "#REF!");
+               confirmPredicate(true, mp, ErrorEval.DIV_ZERO);
+               confirmPredicate(false, mp, ErrorEval.REF_INVALID);
+
+               // not quite an error literal, should be treated as plain text
+               mp = createCriteriaPredicate(new StringEval("<=#REF!a"));
+               confirmPredicate(false, mp, 4);
+               confirmPredicate(true, mp, "#DIV/0!");
+               confirmPredicate(true, mp, "#REF!");
+               confirmPredicate(false, mp, ErrorEval.DIV_ZERO);
+               confirmPredicate(false, mp, ErrorEval.REF_INVALID);
+       }
+
+       public void testWildCards() {
+               I_MatchPredicate mp;
+
+               mp = createCriteriaPredicate(new StringEval("a*b"));
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(true, mp, "ab");
+               confirmPredicate(true, mp, "axxb");
+               confirmPredicate(false, mp, "xab");
+
+               mp = createCriteriaPredicate(new StringEval("a?b"));
+               confirmPredicate(false, mp, "abc");
+               confirmPredicate(false, mp, "ab");
+               confirmPredicate(false, mp, "axxb");
+               confirmPredicate(false, mp, "xab");
+               confirmPredicate(true, mp, "axb");
+
+               mp = createCriteriaPredicate(new StringEval("a~?"));
+               confirmPredicate(false, mp, "a~a");
+               confirmPredicate(false, mp, "a~?");
+               confirmPredicate(true, mp, "a?");
+
+               mp = createCriteriaPredicate(new StringEval("~*a"));
+               confirmPredicate(false, mp, "~aa");
+               confirmPredicate(false, mp, "~*a");
+               confirmPredicate(true, mp, "*a");
+
+               mp = createCriteriaPredicate(new StringEval("12?12"));
+               confirmPredicate(false, mp, 12812);
+               confirmPredicate(true, mp, "12812");
+               confirmPredicate(false, mp, "128812");
+       }
+       public void testNotQuiteWildCards() {
+               I_MatchPredicate mp;
+
+               // make sure special reg-ex chars are treated like normal chars
+               mp = createCriteriaPredicate(new StringEval("a.b"));
+               confirmPredicate(false, mp, "aab");
+               confirmPredicate(true, mp, "a.b");
+
+
+               mp = createCriteriaPredicate(new StringEval("a~b"));
+               confirmPredicate(false, mp, "ab");
+               confirmPredicate(false, mp, "axb");
+               confirmPredicate(false, mp, "a~~b");
+               confirmPredicate(true, mp, "a~b");
+
+               mp = createCriteriaPredicate(new StringEval(">a*b"));
+               confirmPredicate(false, mp, "a(b");
+               confirmPredicate(true, mp, "aab");
+               confirmPredicate(false, mp, "a*a");
+               confirmPredicate(true, mp, "a*c");
+       }
+
+       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, int value) {
+               assertEquals(expectedResult, matchPredicate.matches(new NumberEval(value)));
+       }
+       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, String value) {
+               ValueEval ev = value == null ? BlankEval.instance : new StringEval(value);
+               assertEquals(expectedResult, matchPredicate.matches(ev));
+       }
+       private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, ErrorEval value) {
+               assertEquals(expectedResult, matchPredicate.matches(value));
+       }
+
+       public void testCountifFromSpreadsheet() {
+               testCountFunctionFromSpreadsheet("countifExamples.xls", 1, 2, 3, "countif");
+       }
+
+       public void testCountBlankFromSpreadsheet() {
+               testCountFunctionFromSpreadsheet("countblankExamples.xls", 1, 3, 4, "countblank");
+       }
+
+       private static void testCountFunctionFromSpreadsheet(String FILE_NAME, int START_ROW_IX, int COL_IX_ACTUAL, int COL_IX_EXPECTED, String functionName) {
+
+               int failureCount = 0;
+               HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME);
+               HSSFSheet sheet = wb.getSheetAt(0);
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               int maxRow = sheet.getLastRowNum();
+               for (int rowIx=START_ROW_IX; rowIx<maxRow; rowIx++) {
+                       HSSFRow row = sheet.getRow(rowIx);
+                       if(row == null) {
+                               continue;
+                       }
+                       HSSFCell cell = row.getCell(COL_IX_ACTUAL);
+                       CellValue cv = fe.evaluate(cell);
+                       double actualValue = cv.getNumberValue();
+                       double expectedValue = row.getCell(COL_IX_EXPECTED).getNumericCellValue();
+                       if (actualValue != expectedValue) {
+                               System.err.println("Problem with test case on row " + (rowIx+1) + " "
+                                               + "Expected = (" + expectedValue + ") Actual=(" + actualValue + ") ");
+                               failureCount++;
+                       }
+               }
+
+               if (failureCount > 0) {
+                       throw new AssertionFailedError(failureCount + " " + functionName
+                                       + " evaluations failed. See stderr for more details");
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestDate.java b/src/testcases/org/apache/poi/ss/formula/functions/TestDate.java
new file mode 100644 (file)
index 0000000..64e1c45
--- /dev/null
@@ -0,0 +1,90 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
+ */
+public final class TestDate extends TestCase {
+
+    private HSSFCell cell11;
+    private HSSFFormulaEvaluator evaluator;
+
+    public void setUp() {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet = wb.createSheet("new sheet");
+        cell11 = sheet.createRow(0).createCell(0);
+        cell11.setCellType(HSSFCell.CELL_TYPE_FORMULA);
+        evaluator = new HSSFFormulaEvaluator(wb);
+    }
+
+    /**
+     * Test disabled pending a fix in the formula evaluator
+     * TODO - create MissingArgEval and modify the formula evaluator to handle this
+     */
+    public void DISABLEDtestSomeArgumentsMissing() {
+        confirm("DATE(, 1, 0)", 0.0);
+        confirm("DATE(, 1, 1)", 1.0);
+    }
+
+    public void testValid() {
+
+        confirm("DATE(1900, 1, 1)", 1);
+        confirm("DATE(1900, 1, 32)", 32);
+        confirm("DATE(1900, 222, 1)", 6727);
+        confirm("DATE(1900, 2, 0)", 31);
+        confirm("DATE(2000, 1, 222)", 36747.00);
+        confirm("DATE(2007, 1, 1)", 39083);
+    }
+
+    public void testBugDate() {
+        confirm("DATE(1900, 2, 29)", 60);
+        confirm("DATE(1900, 2, 30)", 61);
+        confirm("DATE(1900, 1, 222)", 222);
+        confirm("DATE(1900, 1, 2222)", 2222);
+        confirm("DATE(1900, 1, 22222)", 22222);
+    }
+
+    public void testPartYears() {
+        confirm("DATE(4, 1, 1)", 1462.00);
+        confirm("DATE(14, 1, 1)", 5115.00);
+        confirm("DATE(104, 1, 1)", 37987.00);
+        confirm("DATE(1004, 1, 1)", 366705.00);
+    }
+
+    private void confirm(String formulaText, double expectedResult) {
+        cell11.setCellFormula(formulaText);
+        evaluator.clearAllCachedResultValues();
+        CellValue cv = evaluator.evaluate(cell11);
+        if (cv.getCellType() != Cell.CELL_TYPE_NUMERIC) {
+            throw new AssertionFailedError("Wrong result type: " + cv.formatAsString());
+        }
+        double actualValue = cv.getNumberValue();
+        assertEquals(expectedResult, actualValue, 0);
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestDays360.java b/src/testcases/org/apache/poi/ss/formula/functions/TestDays360.java
new file mode 100644 (file)
index 0000000..15dd124
--- /dev/null
@@ -0,0 +1,155 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+
+/**
+ * @author Josh Micich
+ */
+public final class TestDays360 extends TestCase {
+
+       /**
+        * @param month 1-based
+        */
+       private static Date makeDate(int year, int month, int day) {
+
+               Calendar cal = new GregorianCalendar(year, month-1, day, 0, 0, 0);
+               cal.set(Calendar.MILLISECOND, 0);
+               return cal.getTime();
+       }
+       private static Date decrementDay(Date d) {
+               Calendar c = new GregorianCalendar();
+               c.setTimeInMillis(d.getTime());
+               c.add(Calendar.DAY_OF_MONTH, -1);
+               return c.getTime();
+       }
+       private static String fmt(Date d) {
+               Calendar c = new GregorianCalendar();
+               c.setTimeInMillis(d.getTime());
+               StringBuilder sb = new StringBuilder();
+               sb.append(c.get(Calendar.YEAR));
+               sb.append("/");
+               sb.append(c.get(Calendar.MONTH)+1);
+               sb.append("/");
+               sb.append(c.get(Calendar.DAY_OF_MONTH));
+               return sb.toString();
+       }
+
+
+       public void testBasic() {
+               confirm(120, 2009, 1, 15, 2009, 5, 15);
+               confirm(158, 2009, 1, 26, 2009, 7, 4);
+
+               // same results in leap years
+               confirm(120, 2008, 1, 15, 2008, 5, 15);
+               confirm(158, 2008, 1, 26, 2008, 7, 4);
+
+               // longer time spans
+               confirm(562, 2008, 8, 11, 2010, 3, 3);
+               confirm(916, 2007, 2, 23, 2009, 9, 9);
+       }
+
+       private static void confirm(int expResult, int y1, int m1, int d1, int y2, int m2, int d2) {
+               confirm(expResult, makeDate(y1, m1, d1), makeDate(y2, m2, d2), false);
+               confirm(-expResult, makeDate(y2, m2, d2), makeDate(y1, m1, d1), false);
+
+       }
+       /**
+        * The <tt>method</tt> parameter only makes a difference when the second parameter
+        * is the last day of the month that does <em>not</em> have 30 days.
+        */
+       public void DISABLED_testMonthBoundaries() {
+               // jan
+               confirmMonthBoundary(false, 1, 0, 0, 2, 3, 4);
+               confirmMonthBoundary(true,  1, 0, 0, 1, 3, 4);
+               // feb
+               confirmMonthBoundary(false, 2,-2, 1, 2, 3, 4);
+               confirmMonthBoundary(true,  2, 0, 1, 2, 3, 4);
+               // mar
+               confirmMonthBoundary(false, 3, 0, 0, 2, 3, 4);
+               confirmMonthBoundary(true,  3, 0, 0, 1, 3, 4);
+               // apr
+               confirmMonthBoundary(false, 4, 0, 1, 2, 3, 4);
+               confirmMonthBoundary(true,  4, 0, 1, 2, 3, 4);
+               // may
+               confirmMonthBoundary(false, 5, 0, 0, 2, 3, 4);
+               confirmMonthBoundary(true,  5, 0, 0, 1, 3, 4);
+               // jun
+               confirmMonthBoundary(false, 6, 0, 1, 2, 3, 4);
+               confirmMonthBoundary(true,  6, 0, 1, 2, 3, 4);
+               // etc...
+       }
+
+
+       /**
+        * @param monthNo 1-based
+        * @param diffs
+        */
+       private static void confirmMonthBoundary(boolean method, int monthNo, int...diffs) {
+               Date firstDayOfNextMonth = makeDate(2001, monthNo+1, 1);
+               Date secondArg = decrementDay(firstDayOfNextMonth);
+               Date firstArg = secondArg;
+
+               for (int i = 0; i < diffs.length; i++) {
+                       int expResult = diffs[i];
+                       confirm(expResult, firstArg, secondArg, method);
+                       firstArg = decrementDay(firstArg);
+               }
+
+       }
+       private static void confirm(int expResult, Date firstArg, Date secondArg, boolean method) {
+
+               ValueEval ve;
+               if (method) {
+                       // TODO enable 3rd arg -
+                       ve = invokeDays360(convert(firstArg), convert(secondArg), BoolEval.valueOf(method));
+               } else {
+                       ve = invokeDays360(convert(firstArg), convert(secondArg));
+               }
+               if (ve instanceof NumberEval) {
+
+                       NumberEval numberEval = (NumberEval) ve;
+                       if (numberEval.getNumberValue() != expResult) {
+                               throw new AssertionFailedError(fmt(firstArg) + " " + fmt(secondArg) + " " + method +
+                                               " wrong result got (" + numberEval.getNumberValue()
+                                               + ") but expected (" + expResult + ")");
+                       }
+                       //      System.err.println(fmt(firstArg) + " " + fmt(secondArg) + " " + method + " success got (" + expResult + ")");
+                       return;
+               }
+               throw new AssertionFailedError("wrong return type (" + ve.getClass().getName() + ")");
+       }
+       private static ValueEval invokeDays360(ValueEval...args) {
+               return new Days360().evaluate(args, -1, -1);
+       }
+       private static NumberEval convert(Date d) {
+               return new NumberEval(HSSFDateUtil.getExcelDate(d));
+       }
+}
+
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestFinanceLib.java b/src/testcases/org/apache/poi/ss/formula/functions/TestFinanceLib.java
new file mode 100644 (file)
index 0000000..90300bf
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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.
+*/
+/*
+ * Created on May 23, 2005
+ *
+ */
+package org.apache.poi.ss.formula.functions;
+
+
+/**
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ *
+ */
+public class TestFinanceLib extends AbstractNumericTestCase {
+
+    public void testFv() {
+        double f, r, y, p, x;
+        int n;
+        boolean t = false;
+        
+        r = 0; n = 3; y = 2; p = 7; t = true;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = -13;
+        assertEquals("fv ", x, f);
+        
+        r = 1; n = 10; y = 100; p = 10000; t = false;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = -10342300;
+        assertEquals("fv ", x, f);
+        
+        r = 1; n = 10; y = 100; p = 10000; t = true;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = -10444600;
+        assertEquals("fv ", x, f);
+        
+        r = 2; n = 12; y = 120; p = 12000; t = false;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = -6409178400d;
+        assertEquals("fv ", x, f);
+        
+        r = 2; n = 12; y = 120; p = 12000; t = true;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = -6472951200d;
+        assertEquals("fv ", x, f);
+        
+        // cross tests with pv
+        r = 2.95; n = 13; y = 13000; p = -4406.78544294496; t = false;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = 333891.230010986; // as returned by excel
+        assertEquals("fv ", x, f);
+        
+        r = 2.95; n = 13; y = 13000; p = -17406.7852148156; t = true;
+        f = FinanceLib.fv(r, n, y, p, t);
+        x = 333891.230102539; // as returned by excel
+        assertEquals("fv ", x, f);
+        
+    }
+    public void testNpv() {
+        double r, v[], npv, x;
+        
+        r = 1; v = new double[]{100, 200, 300, 400};
+        npv = FinanceLib.npv(r, v);
+        x = 162.5;
+        assertEquals("npv ", x, npv);
+        
+        r = 2.5; v = new double[]{1000, 666.66666, 333.33, 12.2768416};
+        npv = FinanceLib.npv(r, v);
+        x = 347.99232604144827;
+        assertEquals("npv ", x, npv);
+        
+        r = 12.33333; v = new double[]{1000, 0, -900, -7777.5765};
+        npv = FinanceLib.npv(r, v);
+        x = 74.3742433377061;
+        assertEquals("npv ", x, npv);
+        
+        r = 0.05; v = new double[]{200000, 300000.55, 400000, 1000000, 6000000, 7000000, -300000};
+        npv = FinanceLib.npv(r, v);
+        x = 11342283.4233124;
+        assertEquals("npv ", x, npv);
+    }
+    public void testPmt() {
+        double f, r, y, p, x;
+        int n;
+        boolean t = false;
+
+        r = 0; n = 3; p = 2; f = 7; t = true;
+        y = FinanceLib.pmt(r, n, p, f, t);
+        x = -3;
+        assertEquals("pmt ", x, y);    
+        
+        // cross check with pv
+        r = 1; n = 10; p = -109.66796875; f = 10000; t = false;
+        y = FinanceLib.pmt(r, n, p, f, t);
+        x = 100;
+        assertEquals("pmt ", x, y);    
+        
+        r = 1; n = 10; p = -209.5703125; f = 10000; t = true;
+        y = FinanceLib.pmt(r, n, p, f, t);
+        x = 100;
+        assertEquals("pmt ", x, y);
+        
+        // cross check with fv
+        r = 2; n = 12; f = -6409178400d; p = 12000; t = false;
+        y = FinanceLib.pmt(r, n, p, f, t);
+        x = 120;
+        assertEquals("pmt ", x, y);    
+        
+        r = 2; n = 12; f = -6472951200d; p = 12000; t = true;
+        y = FinanceLib.pmt(r, n, p, f, t);
+        x = 120;
+        assertEquals("pmt ", x, y);
+    }
+    
+    public void testPv() {
+        double f, r, y, p, x;
+        int n;
+        boolean t = false;
+
+        r = 0; n = 3; y = 2; f = 7; t = true;
+        f = FinanceLib.pv(r, n, y, f, t);
+        x = -13;
+        assertEquals("pv ", x, f);
+
+        r = 1; n = 10; y = 100; f = 10000; t = false;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = -109.66796875;
+        assertEquals("pv ", x, p);    
+        
+        r = 1; n = 10; y = 100; f = 10000; t = true;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = -209.5703125;
+        assertEquals("pv ", x, p);    
+        
+        r = 2.95; n = 13; y = 13000; f = 333891.23; t = false;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = -4406.78544294496;
+        assertEquals("pv ", x, p);
+        
+        r = 2.95; n = 13; y = 13000; f = 333891.23; t = true;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = -17406.7852148156;
+        assertEquals("pv ", x, p);
+        
+        // cross tests with fv
+        r = 2; n = 12; y = 120; f = -6409178400d; t = false;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = 12000;
+        assertEquals("pv ", x, p);
+        
+        r = 2; n = 12; y = 120; f = -6472951200d; t = true;
+        p = FinanceLib.pv(r, n, y, f, t);
+        x = 12000; 
+        assertEquals("pv ", x, p);
+        
+    }
+    
+    public void testNper() {
+        double f, r, y, p, x, n;
+        boolean t = false;
+        
+        r = 0; y = 7; p = 2; f = 3; t = false;
+        n = FinanceLib.nper(r, y, p, f, t);
+        x = -0.71428571429; // can you believe it? excel returns nper as a fraction!??
+        assertEquals("nper ", x, n);    
+        
+        // cross check with pv
+        r = 1; y = 100; p = -109.66796875; f = 10000; t = false;
+        n = FinanceLib.nper(r, y, p, f, t);
+        x = 10;
+        assertEquals("nper ", x, n);    
+        
+        r = 1; y = 100; p = -209.5703125; f = 10000; t = true;
+        n = FinanceLib.nper(r, y, p, f, t);
+        x = 10;
+        assertEquals("nper ", x, n);
+        
+        // cross check with fv
+        r = 2; y = 120; f = -6409178400d; p = 12000; t = false;
+        n = FinanceLib.nper(r, y, p, f, t);
+        x = 12;
+        assertEquals("nper ", x, n);    
+        
+        r = 2; y = 120; f = -6472951200d; p = 12000; t = true;
+        n = FinanceLib.nper(r, y, p, f, t);
+        x = 12; 
+        assertEquals("nper ", x, n);
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestFind.java b/src/testcases/org/apache/poi/ss/formula/functions/TestFind.java
new file mode 100644 (file)
index 0000000..a78e89d
--- /dev/null
@@ -0,0 +1,76 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Tests for {@link Financed}
+ * 
+ * @author Torstein Svendsen (torstei@officenet.no)
+ */
+public final class TestFind extends TestCase {
+
+       public void testFind() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFCell cell = wb.createSheet().createRow(0).createCell(0);
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+
+               confirmResult(fe, cell, "find(\"h\", \"haystack\")", 1);
+               confirmResult(fe, cell, "find(\"a\", \"haystack\",2)", 2);
+               confirmResult(fe, cell, "find(\"a\", \"haystack\",3)", 6);
+
+               // number args converted to text
+               confirmResult(fe, cell, "find(7, 32768)", 3);
+               confirmResult(fe, cell, "find(\"34\", 1341235233412, 3)", 10);
+               confirmResult(fe, cell, "find(5, 87654)", 4);
+
+               // Errors
+               confirmError(fe, cell, "find(\"n\", \"haystack\")", HSSFErrorConstants.ERROR_VALUE);
+               confirmError(fe, cell, "find(\"k\", \"haystack\",9)", HSSFErrorConstants.ERROR_VALUE);
+               confirmError(fe, cell, "find(\"k\", \"haystack\",#REF!)", HSSFErrorConstants.ERROR_REF);
+               confirmError(fe, cell, "find(\"k\", \"haystack\",0)", HSSFErrorConstants.ERROR_VALUE);
+               confirmError(fe, cell, "find(#DIV/0!, #N/A, #REF!)", HSSFErrorConstants.ERROR_DIV_0);
+               confirmError(fe, cell, "find(2, #N/A, #REF!)", HSSFErrorConstants.ERROR_NA);
+       }
+
+       private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
+                       int expectedResult) {
+               cell.setCellFormula(formulaText);
+               fe.notifyUpdateCell(cell);
+               CellValue result = fe.evaluate(cell);
+               assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_NUMERIC);
+               assertEquals(expectedResult, result.getNumberValue(), 0.0);
+       }
+
+       private static void confirmError(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
+                       int expectedErrorCode) {
+               cell.setCellFormula(formulaText);
+               fe.notifyUpdateCell(cell);
+               CellValue result = fe.evaluate(cell);
+               assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_ERROR);
+               assertEquals(expectedErrorCode, result.getErrorValue());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIndex.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIndex.java
new file mode 100644 (file)
index 0000000..ce03252
--- /dev/null
@@ -0,0 +1,157 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.util.Arrays;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.MissingArgEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.WorkbookEvaluator;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * Tests for the INDEX() function.</p>
+ *
+ * This class contains just a few specific cases that directly invoke {@link Index},
+ * with minimum overhead.<br/>
+ * Another test: {@link TestIndexFunctionFromSpreadsheet} operates from a higher level
+ * and has far greater coverage of input permutations.<br/>
+ *
+ * @author Josh Micich
+ */
+public final class TestIndex extends TestCase {
+
+       private static final Index FUNC_INST = new Index();
+       private static final double[] TEST_VALUES0 = {
+                       1, 2,
+                       3, 4,
+                       5, 6,
+                       7, 8,
+                       9, 10,
+                       11, 12,
+       };
+
+       /**
+        * For the case when the first argument to INDEX() is an area reference
+        */
+       public void testEvaluateAreaReference() {
+
+               double[] values = TEST_VALUES0;
+               confirmAreaEval("C1:D6", values, 4, 1, 7);
+               confirmAreaEval("C1:D6", values, 6, 2, 12);
+               confirmAreaEval("C1:D6", values, 3, 1, 5);
+
+               // now treat same data as 3 columns, 4 rows
+               confirmAreaEval("C10:E13", values, 2, 2, 5);
+               confirmAreaEval("C10:E13", values, 4, 1, 10);
+       }
+
+       /**
+        * @param areaRefString in Excel notation e.g. 'D2:E97'
+        * @param dValues array of evaluated values for the area reference
+        * @param rowNum 1-based
+        * @param colNum 1-based, pass -1 to signify argument not present
+        */
+       private static void confirmAreaEval(String areaRefString, double[] dValues,
+                       int rowNum, int colNum, double expectedResult) {
+               ValueEval[] values = new ValueEval[dValues.length];
+               for (int i = 0; i < values.length; i++) {
+                       values[i] = new NumberEval(dValues[i]);
+               }
+               AreaEval arg0 = EvalFactory.createAreaEval(areaRefString, values);
+
+               ValueEval[] args;
+               if (colNum > 0) {
+                       args = new ValueEval[] { arg0, new NumberEval(rowNum), new NumberEval(colNum), };
+               } else {
+                       args = new ValueEval[] { arg0, new NumberEval(rowNum), };
+               }
+
+               double actual = invokeAndDereference(args);
+               assertEquals(expectedResult, actual, 0D);
+       }
+
+       private static double invokeAndDereference(ValueEval[] args) {
+               ValueEval ve = FUNC_INST.evaluate(args, -1, -1);
+               ve = WorkbookEvaluator.dereferenceResult(ve, -1, -1);
+               assertEquals(NumberEval.class, ve.getClass());
+               return ((NumberEval)ve).getNumberValue();
+       }
+
+       /**
+        * Tests expressions like "INDEX(A1:C1,,2)".<br/>
+        * This problem was found while fixing bug 47048 and is observable up to svn r773441.
+        */
+       public void testMissingArg() {
+               ValueEval[] values = {
+                               new NumberEval(25.0),
+                               new NumberEval(26.0),
+                               new NumberEval(28.0),
+               };
+               AreaEval arg0 = EvalFactory.createAreaEval("A10:C10", values);
+               ValueEval[] args = new ValueEval[] { arg0, MissingArgEval.instance, new NumberEval(2), };
+               ValueEval actualResult;
+               try {
+                       actualResult = FUNC_INST.evaluate(args, -1, -1);
+               } catch (RuntimeException e) {
+                       if (e.getMessage().equals("Unexpected arg eval type (org.apache.poi.hssf.record.formula.eval.MissingArgEval")) {
+                               throw new AssertionFailedError("Identified bug 47048b - INDEX() should support missing-arg");
+                       }
+                       throw e;
+               }
+               // result should be an area eval "B10:B10"
+               AreaEval ae = confirmAreaEval("B10:B10", actualResult);
+               actualResult = ae.getValue(0, 0);
+               assertEquals(NumberEval.class, actualResult.getClass());
+               assertEquals(26.0, ((NumberEval)actualResult).getNumberValue(), 0.0);
+       }
+
+       /**
+        * When the argument to INDEX is a reference, the result should be a reference
+        * A formula like "OFFSET(INDEX(A1:B2,2,1),1,1,1,1)" should return the value of cell B3.
+        * This works because the INDEX() function returns a reference to A2 (not the value of A2)
+        */
+       public void testReferenceResult() {
+               ValueEval[] values = new ValueEval[4];
+               Arrays.fill(values, NumberEval.ZERO);
+               AreaEval arg0 = EvalFactory.createAreaEval("A1:B2", values);
+               ValueEval[] args = new ValueEval[] { arg0, new NumberEval(2), new NumberEval(1), };
+               ValueEval ve = FUNC_INST.evaluate(args, -1, -1);
+               confirmAreaEval("A2:A2", ve);
+       }
+
+       /**
+        * Confirms that the result is an area ref with the specified coordinates
+        * @return <tt>ve</tt> cast to {@link AreaEval} if it is valid
+        */
+       private static AreaEval confirmAreaEval(String refText, ValueEval ve) {
+               CellRangeAddress cra = CellRangeAddress.valueOf(refText);
+               assertTrue(ve instanceof AreaEval);
+               AreaEval ae = (AreaEval) ve;
+               assertEquals(cra.getFirstRow(), ae.getFirstRow());
+               assertEquals(cra.getFirstColumn(), ae.getFirstColumn());
+               assertEquals(cra.getLastRow(), ae.getLastRow());
+               assertEquals(cra.getLastColumn(), ae.getLastColumn());
+               return ae;
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIndexFunctionFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIndexFunctionFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..c297843
--- /dev/null
@@ -0,0 +1,250 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.io.PrintStream;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Tests INDEX() as loaded from a test data spreadsheet.<p/>
+ *
+ * @author Josh Micich
+ */
+public final class TestIndexFunctionFromSpreadsheet extends TestCase {
+
+       private static final class Result {
+               public static final int SOME_EVALUATIONS_FAILED = -1;
+               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
+               public static final int NO_EVALUATIONS_FOUND = 0;
+       }
+
+       /**
+        * This class defines constants for navigating around the test data spreadsheet used for these tests.
+        */
+       private static final class SS {
+
+               /** Name of the test spreadsheet (found in the standard test data folder) */
+               public final static String FILENAME = "IndexFunctionTestCaseData.xls";
+
+               public static final int COLUMN_INDEX_EVALUATION = 2; // Column 'C'
+               public static final int COLUMN_INDEX_EXPECTED_RESULT = 3; // Column 'D'
+
+       }
+
+       // Note - multiple failures are aggregated before ending.
+       // If one or more functions fail, a single AssertionFailedError is thrown at the end
+       private int _evaluationFailureCount;
+       private int _evaluationSuccessCount;
+
+
+
+       private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
+               if (expected == null) {
+                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
+               }
+               if(actual == null) {
+                       throw new AssertionFailedError(msg + " - actual value was null");
+               }
+               if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
+                       confirmErrorResult(msg, expected.getErrorCellValue(), actual);
+                       return;
+               }
+               if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
+                       throw unexpectedError(msg, expected, actual.getErrorValue());
+               }
+               if(actual.getCellType() != expected.getCellType()) {
+                       throw wrongTypeError(msg, expected, actual);
+               }
+
+
+               switch (expected.getCellType()) {
+                       case HSSFCell.CELL_TYPE_BOOLEAN:
+                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
+                               break;
+                       case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
+                               throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
+                       case HSSFCell.CELL_TYPE_NUMERIC:
+                               assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
+                               break;
+                       case HSSFCell.CELL_TYPE_STRING:
+                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
+                               break;
+               }
+       }
+
+
+       private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
+               return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
+                               + actualValue.formatAsString()
+                               + " but the expected result was "
+                               + formatValue(expectedCell)
+                               );
+       }
+       private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
+               return new AssertionFailedError(msgPrefix + " Error code ("
+                               + ErrorEval.getText(actualErrorCode)
+                               + ") was evaluated, but the expected result was "
+                               + formatValue(expected)
+                               );
+       }
+
+
+       private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
+               if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
+                       throw new AssertionFailedError(msgPrefix + " Expected cell error ("
+                                       + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
+                                       + actual.formatAsString());
+               }
+               if(expectedErrorCode != actual.getErrorValue()) {
+                       throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
+                                       + ErrorEval.getText(expectedErrorCode)
+                                       + ") but actual error code was ("
+                                       + ErrorEval.getText(actual.getErrorValue())
+                                       + ")");
+               }
+       }
+
+
+       private static String formatValue(HSSFCell expecedCell) {
+               switch (expecedCell.getCellType()) {
+                       case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
+                       case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
+                       case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
+                       case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
+               }
+               throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
+       }
+
+
+       protected void setUp() {
+               _evaluationFailureCount = 0;
+               _evaluationSuccessCount = 0;
+       }
+
+       public void testFunctionsFromTestSpreadsheet() {
+               HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
+
+               processTestSheet(workbook, workbook.getSheetName(0));
+
+               // confirm results
+               String successMsg = "There were "
+                               + _evaluationSuccessCount + " function(s) without error";
+               if(_evaluationFailureCount > 0) {
+                       String msg = _evaluationFailureCount + " evaluation(s) failed.  " + successMsg;
+                       throw new AssertionFailedError(msg);
+               }
+               if(false) { // normally no output for successful tests
+                       System.out.println(getClass().getName() + ": " + successMsg);
+               }
+       }
+
+       private void processTestSheet(HSSFWorkbook workbook, String sheetName) {
+               HSSFSheet sheet = workbook.getSheetAt(0);
+               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
+               int maxRows = sheet.getLastRowNum()+1;
+               int result = Result.NO_EVALUATIONS_FOUND; // so far
+
+               for(int rowIndex=0; rowIndex<maxRows; rowIndex++) {
+                       HSSFRow r = sheet.getRow(rowIndex);
+                       if(r == null) {
+                               continue;
+                       }
+                       HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
+                       if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
+                               continue;
+                       }
+                       HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
+
+                       String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c);
+                       try {
+                               CellValue actualValue = evaluator.evaluate(c);
+                               confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
+                               _evaluationSuccessCount ++;
+                               if(result != Result.SOME_EVALUATIONS_FAILED) {
+                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
+                               }
+                       } catch (RuntimeException e) {
+                               _evaluationFailureCount ++;
+                               printShortStackTrace(System.err, e, msgPrefix);
+                               result = Result.SOME_EVALUATIONS_FAILED;
+                       } catch (AssertionFailedError e) {
+                               _evaluationFailureCount ++;
+                               printShortStackTrace(System.err, e, msgPrefix);
+                               result = Result.SOME_EVALUATIONS_FAILED;
+                       }
+               }
+       }
+
+
+       private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c) {
+
+               StringBuffer sb = new StringBuffer();
+               CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
+               sb.append(cr.formatAsString());
+               sb.append(" [formula: ").append(c.getCellFormula()).append(" ]");
+               return sb.toString();
+       }
+
+       /**
+        * Useful to keep output concise when expecting many failures to be reported by this test case
+        */
+       private static void printShortStackTrace(PrintStream ps, Throwable e, String msgPrefix) {
+               System.err.println("Problem with " + msgPrefix);
+               StackTraceElement[] stes = e.getStackTrace();
+
+               int startIx = 0;
+               // skip any top frames inside junit.framework.Assert
+               while(startIx<stes.length) {
+                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
+                               break;
+                       }
+                       startIx++;
+               }
+               // skip bottom frames (part of junit framework)
+               int endIx = startIx+1;
+               while(endIx < stes.length) {
+                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
+                               break;
+                       }
+                       endIx++;
+               }
+               if(startIx >= endIx) {
+                       // something went wrong. just print the whole stack trace
+                       e.printStackTrace(ps);
+               }
+               endIx -= 4; // skip 4 frames of reflection invocation
+               ps.println(e.toString());
+               for(int i=startIx; i<endIx; i++) {
+                       ps.println("\tat " + stes[i].toString());
+               }
+       }
+}
+
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIndirect.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIndirect.java
new file mode 100644 (file)
index 0000000..3a35ed9
--- /dev/null
@@ -0,0 +1,193 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+
+/**
+ * Tests for the INDIRECT() function.</p>
+ *
+ * @author Josh Micich
+ */
+public final class TestIndirect extends TestCase {
+       // convenient access to namespace
+       private static final ErrorEval EE = null;
+
+       private static void createDataRow(HSSFSheet sheet, int rowIndex, double... vals) {
+               HSSFRow row = sheet.createRow(rowIndex);
+               for (int i = 0; i < vals.length; i++) {
+                       row.createCell(i).setCellValue(vals[i]);
+               }
+       }
+
+       private static HSSFWorkbook createWBA() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet1 = wb.createSheet("Sheet1");
+               HSSFSheet sheet2 = wb.createSheet("Sheet2");
+               HSSFSheet sheet3 = wb.createSheet("John's sales");
+
+               createDataRow(sheet1, 0, 11, 12, 13, 14);
+               createDataRow(sheet1, 1, 21, 22, 23, 24);
+               createDataRow(sheet1, 2, 31, 32, 33, 34);
+
+               createDataRow(sheet2, 0, 50, 55, 60, 65);
+               createDataRow(sheet2, 1, 51, 56, 61, 66);
+               createDataRow(sheet2, 2, 52, 57, 62, 67);
+
+               createDataRow(sheet3, 0, 30, 31, 32);
+               createDataRow(sheet3, 1, 33, 34, 35);
+
+        HSSFName name1 = wb.createName();
+        name1.setNameName("sales1");
+        name1.setRefersToFormula("Sheet1!A1:D1");
+
+        HSSFName name2 = wb.createName();
+        name2.setNameName("sales2");
+        name2.setRefersToFormula("Sheet2!B1:C3");
+
+        HSSFRow row = sheet1.createRow(3);
+        row.createCell(0).setCellValue("sales1");  //A4
+        row.createCell(1).setCellValue("sales2");  //B4
+
+               return wb;
+       }
+
+       private static HSSFWorkbook createWBB() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet1 = wb.createSheet("Sheet1");
+               HSSFSheet sheet2 = wb.createSheet("Sheet2");
+               HSSFSheet sheet3 = wb.createSheet("## Look here!");
+
+               createDataRow(sheet1, 0, 400, 440, 480, 520);
+               createDataRow(sheet1, 1, 420, 460, 500, 540);
+
+               createDataRow(sheet2, 0, 50, 55, 60, 65);
+               createDataRow(sheet2, 1, 51, 56, 61, 66);
+
+               createDataRow(sheet3, 0, 42);
+
+               return wb;
+       }
+
+       public void testBasic() {
+
+               HSSFWorkbook wbA = createWBA();
+               HSSFCell c = wbA.getSheetAt(0).createRow(5).createCell(2);
+               HSSFFormulaEvaluator feA = new HSSFFormulaEvaluator(wbA);
+
+               // non-error cases
+               confirm(feA, c, "INDIRECT(\"C2\")", 23);
+               confirm(feA, c, "INDIRECT(\"$C2\")", 23);
+               confirm(feA, c, "INDIRECT(\"C$2\")", 23);
+               confirm(feA, c, "SUM(INDIRECT(\"Sheet2!B1:C3\"))", 351); // area ref
+               confirm(feA, c, "SUM(INDIRECT(\"Sheet2! B1 : C3 \"))", 351); // spaces in area ref
+               confirm(feA, c, "SUM(INDIRECT(\"'John''s sales'!A1:C1\"))", 93); // special chars in sheet name
+               confirm(feA, c, "INDIRECT(\"'Sheet1'!B3\")", 32); // redundant sheet name quotes
+               confirm(feA, c, "INDIRECT(\"sHeet1!B3\")", 32); // case-insensitive sheet name
+               confirm(feA, c, "INDIRECT(\" D3 \")", 34); // spaces around cell ref
+               confirm(feA, c, "INDIRECT(\"Sheet1! D3 \")", 34); // spaces around cell ref
+               confirm(feA, c, "INDIRECT(\"A1\", TRUE)", 11); // explicit arg1. only TRUE supported so far
+
+               confirm(feA, c, "INDIRECT(\"A1:G1\")", 13); // de-reference area ref (note formula is in C4)
+
+        confirm(feA, c, "SUM(INDIRECT(A4))", 50); // indirect defined name
+        confirm(feA, c, "SUM(INDIRECT(B4))", 351); // indirect defined name pointinh to other sheet
+
+               // simple error propagation:
+
+               // arg0 is evaluated to text first
+               confirm(feA, c, "INDIRECT(#DIV/0!)", EE.DIV_ZERO);
+               confirm(feA, c, "INDIRECT(#DIV/0!)", EE.DIV_ZERO);
+               confirm(feA, c, "INDIRECT(#NAME?, \"x\")", EE.NAME_INVALID);
+               confirm(feA, c, "INDIRECT(#NUM!, #N/A)", EE.NUM_ERROR);
+
+               // arg1 is evaluated to boolean before arg0 is decoded
+               confirm(feA, c, "INDIRECT(\"garbage\", #N/A)", EE.NA);
+               confirm(feA, c, "INDIRECT(\"garbage\", \"\")", EE.VALUE_INVALID); // empty string is not valid boolean
+               confirm(feA, c, "INDIRECT(\"garbage\", \"flase\")", EE.VALUE_INVALID); // must be "TRUE" or "FALSE"
+
+
+               // spaces around sheet name (with or without quotes makes no difference)
+               confirm(feA, c, "INDIRECT(\"'Sheet1 '!D3\")", EE.REF_INVALID);
+               confirm(feA, c, "INDIRECT(\" Sheet1!D3\")", EE.REF_INVALID);
+               confirm(feA, c, "INDIRECT(\"'Sheet1' !D3\")", EE.REF_INVALID);
+
+
+               confirm(feA, c, "SUM(INDIRECT(\"'John's sales'!A1:C1\"))", EE.REF_INVALID); // bad quote escaping
+               confirm(feA, c, "INDIRECT(\"[Book1]Sheet1!A1\")", EE.REF_INVALID); // unknown external workbook
+               confirm(feA, c, "INDIRECT(\"Sheet3!A1\")", EE.REF_INVALID); // unknown sheet
+               if (false) { // TODO - support evaluation of defined names
+                       confirm(feA, c, "INDIRECT(\"Sheet1!IW1\")", EE.REF_INVALID); // bad column
+                       confirm(feA, c, "INDIRECT(\"Sheet1!A65537\")", EE.REF_INVALID); // bad row
+               }
+               confirm(feA, c, "INDIRECT(\"Sheet1!A 1\")", EE.REF_INVALID); // space in cell ref
+       }
+
+       public void testMultipleWorkbooks() {
+               HSSFWorkbook wbA = createWBA();
+               HSSFCell cellA = wbA.getSheetAt(0).createRow(10).createCell(0);
+               HSSFFormulaEvaluator feA = new HSSFFormulaEvaluator(wbA);
+
+               HSSFWorkbook wbB = createWBB();
+               HSSFCell cellB = wbB.getSheetAt(0).createRow(10).createCell(0);
+               HSSFFormulaEvaluator feB = new HSSFFormulaEvaluator(wbB);
+
+               String[] workbookNames = { "MyBook", "Figures for January", };
+               HSSFFormulaEvaluator[] evaluators = { feA, feB, };
+               HSSFFormulaEvaluator.setupEnvironment(workbookNames, evaluators);
+
+               confirm(feB, cellB, "INDIRECT(\"'[Figures for January]## Look here!'!A1\")", 42); // same wb
+               confirm(feA, cellA, "INDIRECT(\"'[Figures for January]## Look here!'!A1\")", 42); // across workbooks
+
+               // 2 level recursion
+               confirm(feB, cellB, "INDIRECT(\"[MyBook]Sheet2!A1\")", 50); // set up (and check) first level
+               confirm(feA, cellA, "INDIRECT(\"'[Figures for January]Sheet1'!A11\")", 50); // points to cellB
+       }
+
+       private static void confirm(FormulaEvaluator fe, Cell cell, String formula,
+                       double expectedResult) {
+               fe.clearAllCachedResultValues();
+               cell.setCellFormula(formula);
+               CellValue cv = fe.evaluate(cell);
+               if (cv.getCellType() != Cell.CELL_TYPE_NUMERIC) {
+                       throw new AssertionFailedError("expected numeric cell type but got " + cv.formatAsString());
+               }
+               assertEquals(expectedResult, cv.getNumberValue(), 0.0);
+       }
+       private static void confirm(FormulaEvaluator fe, Cell cell, String formula,
+                       ErrorEval expectedResult) {
+               fe.clearAllCachedResultValues();
+               cell.setCellFormula(formula);
+               CellValue cv = fe.evaluate(cell);
+               if (cv.getCellType() != Cell.CELL_TYPE_ERROR) {
+                       throw new AssertionFailedError("expected error cell type but got " + cv.formatAsString());
+               }
+               int expCode = expectedResult.getErrorCode();
+               if (cv.getErrorValue() != expCode) {
+                       throw new AssertionFailedError("Expected error '" + EE.getText(expCode)
+                                       + "' but got '" + cv.formatAsString() + "'.");
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIsBlank.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIsBlank.java
new file mode 100644 (file)
index 0000000..6b40f9c
--- /dev/null
@@ -0,0 +1,58 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+/**
+ * Tests for Excel function ISBLANK()
+ * 
+ * @author Josh Micich
+ */
+public final class TestIsBlank extends TestCase {
+
+       public void test3DArea() {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet1 = wb.createSheet();
+        wb.setSheetName(0, "Sheet1");
+        wb.createSheet();
+        wb.setSheetName(1, "Sheet2");
+        HSSFRow row = sheet1.createRow(0);
+        HSSFCell cell = row.createCell(0);
+
+         
+        cell.setCellFormula("isblank(Sheet2!A1:A1)");
+        
+        HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+        CellValue result = fe.evaluate(cell);
+        assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, result.getCellType());
+        assertEquals(true, result.getBooleanValue());
+        
+        cell.setCellFormula("isblank(D7:D7)");
+        
+        result = fe.evaluate(cell);
+        assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, result.getCellType());
+        assertEquals(true, result.getBooleanValue());
+   }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLeftRight.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLeftRight.java
new file mode 100644 (file)
index 0000000..58160bd
--- /dev/null
@@ -0,0 +1,73 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test cases for {@link TextFunction#LEFT} and {@link TextFunction#RIGHT}
+ * 
+ * @author Brendan Nolan
+ *
+ */
+public class TestLeftRight extends TestCase {
+
+       private static final NumberEval NEGATIVE_OPERAND = new NumberEval(-1.0);
+       private static final StringEval ANY_STRING_VALUE = new StringEval("ANYSTRINGVALUE");
+
+       
+       private static ValueEval invokeLeft(ValueEval text, ValueEval operand) {
+               ValueEval[] args = new ValueEval[] { text, operand };
+               return TextFunction.LEFT.evaluate(args, -1, (short)-1);
+       }
+       
+       private static ValueEval invokeRight(ValueEval text, ValueEval operand) {
+               ValueEval[] args = new ValueEval[] { text, operand };
+               return TextFunction.RIGHT.evaluate(args, -1, (short)-1);
+       }
+       
+       public void testLeftRight_bug49841() {
+
+               try {
+                       invokeLeft(ANY_STRING_VALUE, NEGATIVE_OPERAND);
+                       invokeRight(ANY_STRING_VALUE, NEGATIVE_OPERAND);
+               } catch (StringIndexOutOfBoundsException e) {
+                       fail("Identified bug 49841");
+               }
+
+       }
+       
+       public void testLeftRightNegativeOperand() {
+               
+               assertEquals(ErrorEval.VALUE_INVALID, invokeRight(ANY_STRING_VALUE, NEGATIVE_OPERAND));         
+               assertEquals(ErrorEval.VALUE_INVALID, invokeLeft(ANY_STRING_VALUE, NEGATIVE_OPERAND));
+
+       }
+       
+       
+       
+       
+
+       
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLen.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLen.java
new file mode 100644 (file)
index 0000000..a9a3d4c
--- /dev/null
@@ -0,0 +1,72 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+/**
+ * Tests for Excel function LEN()
+ *
+ * @author Josh Micich
+ */
+public final class TestLen extends TestCase {
+
+       private static ValueEval invokeLen(ValueEval text) {
+               ValueEval[] args = new ValueEval[] { text, };
+               return TextFunction.LEN.evaluate(args, -1, (short)-1);
+       }
+
+       private void confirmLen(ValueEval text, int expected) {
+               ValueEval result = invokeLen(text);
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
+       }
+
+       private void confirmLen(ValueEval text, ErrorEval expectedError) {
+               ValueEval result = invokeLen(text);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
+       }
+
+       public void testBasic() {
+
+               confirmLen(new StringEval("galactic"), 8);
+       }
+
+       /**
+        * Valid cases where text arg is not exactly a string
+        */
+       public void testUnusualArgs() {
+
+               // text (first) arg type is number, other args are strings with fractional digits
+               confirmLen(new NumberEval(123456), 6);
+               confirmLen(BoolEval.FALSE, 5);
+               confirmLen(BoolEval.TRUE, 4);
+               confirmLen(BlankEval.instance, 0);
+       }
+
+       public void testErrors() {
+               confirmLen(ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLookupFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLookupFunctionsFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..6054d08
--- /dev/null
@@ -0,0 +1,365 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.io.PrintStream;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.ss.usermodel.CellValue;
+
+/**
+ * Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.<p/>
+ * These tests have been separated from the common function and operator tests because the lookup
+ * functions have more complex test cases and test data setup.
+ *
+ * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class
+ * (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor, where execution can be observed
+ *  more easily.
+ *
+ * @author Josh Micich
+ */
+public final class TestLookupFunctionsFromSpreadsheet extends TestCase {
+
+       private static final class Result {
+               public static final int SOME_EVALUATIONS_FAILED = -1;
+               public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
+               public static final int NO_EVALUATIONS_FOUND = 0;
+       }
+
+       /**
+        * This class defines constants for navigating around the test data spreadsheet used for these tests.
+        */
+       private static final class SS {
+
+               /** Name of the test spreadsheet (found in the standard test data folder) */
+               public final static String FILENAME = "LookupFunctionsTestCaseData.xls";
+
+               /** Name of the first sheet in the spreadsheet (contains comments) */
+               public final static String README_SHEET_NAME = "Read Me";
+
+
+               /** Row (zero-based) in each sheet where the evaluation cases start.   */
+               public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5'
+               /**  Index of the column that contains the function names */
+               public static final int COLUMN_INDEX_MARKER = 0; // Column 'A'
+               public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B'
+               public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C'
+               public static final int COLUMN_ROW_COMMENT = 3; // Column 'D'
+
+               /** Used to indicate when there are no more test cases on the current sheet   */
+               public static final String TEST_CASES_END_MARKER = "<end>";
+               /** Used to indicate that the test on the current row should be ignored */
+               public static final String SKIP_CURRENT_TEST_CASE_MARKER = "<skip>";
+
+       }
+
+       // Note - multiple failures are aggregated before ending.
+       // If one or more functions fail, a single AssertionFailedError is thrown at the end
+       private int _sheetFailureCount;
+       private int _sheetSuccessCount;
+       private int _evaluationFailureCount;
+       private int _evaluationSuccessCount;
+
+
+
+       private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
+               if (expected == null) {
+                       throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
+               }
+               if(actual == null) {
+                       throw new AssertionFailedError(msg + " - actual value was null");
+               }
+               if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
+                       confirmErrorResult(msg, expected.getErrorCellValue(), actual);
+                       return;
+               }
+               if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
+                       throw unexpectedError(msg, expected, actual.getErrorValue());
+               }
+               if(actual.getCellType() != expected.getCellType()) {
+                       throw wrongTypeError(msg, expected, actual);
+               }
+
+
+               switch (expected.getCellType()) {
+                       case HSSFCell.CELL_TYPE_BOOLEAN:
+                               assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
+                               break;
+                       case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
+                               throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg);
+                       case HSSFCell.CELL_TYPE_NUMERIC:
+                               assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
+                               break;
+                       case HSSFCell.CELL_TYPE_STRING:
+                               assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
+                               break;
+               }
+       }
+
+
+       private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
+               return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
+                               + actualValue.formatAsString()
+                               + " but the expected result was "
+                               + formatValue(expectedCell)
+                               );
+       }
+       private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
+               return new AssertionFailedError(msgPrefix + " Error code ("
+                               + ErrorEval.getText(actualErrorCode)
+                               + ") was evaluated, but the expected result was "
+                               + formatValue(expected)
+                               );
+       }
+
+
+       private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
+               if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
+                       throw new AssertionFailedError(msgPrefix + " Expected cell error ("
+                                       + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
+                                       + actual.formatAsString());
+               }
+               if(expectedErrorCode != actual.getErrorValue()) {
+                       throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
+                                       + ErrorEval.getText(expectedErrorCode)
+                                       + ") but actual error code was ("
+                                       + ErrorEval.getText(actual.getErrorValue())
+                                       + ")");
+               }
+       }
+
+
+       private static String formatValue(HSSFCell expecedCell) {
+               switch (expecedCell.getCellType()) {
+                       case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
+                       case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
+                       case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
+                       case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
+               }
+               throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
+       }
+
+
+       protected void setUp() {
+               _sheetFailureCount = 0;
+               _sheetSuccessCount = 0;
+               _evaluationFailureCount = 0;
+               _evaluationSuccessCount = 0;
+       }
+
+       public void testFunctionsFromTestSpreadsheet() {
+               HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
+
+               confirmReadMeSheet(workbook);
+               int nSheets = workbook.getNumberOfSheets();
+               for(int i=1; i< nSheets; i++) {
+                       int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i));
+                       switch(sheetResult) {
+                               case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break;
+                               case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break;
+                       }
+               }
+
+               // confirm results
+               String successMsg = "There were "
+                               + _sheetSuccessCount + " successful sheets(s) and "
+                               + _evaluationSuccessCount + " function(s) without error";
+               if(_sheetFailureCount > 0) {
+                       String msg = _sheetFailureCount + " sheets(s) failed with "
+                       + _evaluationFailureCount + " evaluation(s).  " + successMsg;
+                       throw new AssertionFailedError(msg);
+               }
+               if(false) { // normally no output for successful tests
+                       System.out.println(getClass().getName() + ": " + successMsg);
+               }
+       }
+
+       private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {
+               HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
+               HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
+               int maxRows = sheet.getLastRowNum()+1;
+               int result = Result.NO_EVALUATIONS_FOUND; // so far
+
+               String currentGroupComment = null;
+               for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndex<maxRows; rowIndex++) {
+                       HSSFRow r = sheet.getRow(rowIndex);
+                       String newMarkerValue = getMarkerColumnValue(r);
+                       if(r == null) {
+                               continue;
+                       }
+                       if(SS.TEST_CASES_END_MARKER.equalsIgnoreCase(newMarkerValue)) {
+                               // normal exit point
+                               return result;
+                       }
+                       if(SS.SKIP_CURRENT_TEST_CASE_MARKER.equalsIgnoreCase(newMarkerValue)) {
+                               // currently disabled test case row
+                               continue;
+                       }
+                       if(newMarkerValue != null) {
+                               currentGroupComment = newMarkerValue;
+                       }
+                       HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
+                       if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
+                               continue;
+                       }
+                       CellValue actualValue = evaluator.evaluate(c);
+                       HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
+                       String rowComment = getRowCommentColumnValue(r);
+
+                       String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c, currentGroupComment, rowComment);
+                       try {
+                               confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
+                               _evaluationSuccessCount ++;
+                               if(result != Result.SOME_EVALUATIONS_FAILED) {
+                                       result = Result.ALL_EVALUATIONS_SUCCEEDED;
+                               }
+                       } catch (RuntimeException e) {
+                               _evaluationFailureCount ++;
+                               printShortStackTrace(System.err, e);
+                               result = Result.SOME_EVALUATIONS_FAILED;
+                       } catch (AssertionFailedError e) {
+                               _evaluationFailureCount ++;
+                               printShortStackTrace(System.err, e);
+                               result = Result.SOME_EVALUATIONS_FAILED;
+                       }
+
+               }
+               throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER
+                               + "' on sheet '" + sheetName + "'");
+
+       }
+
+
+       private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c, String currentGroupComment,
+                       String rowComment) {
+
+               StringBuffer sb = new StringBuffer();
+               CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
+               sb.append(cr.formatAsString());
+               sb.append(" {=").append(c.getCellFormula()).append("}");
+
+               if(currentGroupComment != null) {
+                       sb.append(" '");
+                       sb.append(currentGroupComment);
+                       if(rowComment != null) {
+                               sb.append(" - ");
+                               sb.append(rowComment);
+                       }
+                       sb.append("' ");
+               } else {
+                       if(rowComment != null) {
+                               sb.append(" '");
+                               sb.append(rowComment);
+                               sb.append("' ");
+                       }
+               }
+
+               return sb.toString();
+       }
+
+       /**
+        * Asserts that the 'read me' comment page exists, and has this class' name in one of the
+        * cells.  This back-link is to make it easy to find this class if a reader encounters the
+        * spreadsheet first.
+        */
+       private void confirmReadMeSheet(HSSFWorkbook workbook) {
+               String firstSheetName = workbook.getSheetName(0);
+               if(!firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)) {
+                       throw new RuntimeException("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'");
+               }
+               HSSFSheet sheet = workbook.getSheetAt(0);
+               String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString();
+               assertEquals("Test class name in spreadsheet comment", getClass().getName(), specifiedClassName);
+       }
+
+
+       /**
+        * Useful to keep output concise when expecting many failures to be reported by this test case
+        */
+       private static void printShortStackTrace(PrintStream ps, Throwable e) {
+               StackTraceElement[] stes = e.getStackTrace();
+
+               int startIx = 0;
+               // skip any top frames inside junit.framework.Assert
+               while(startIx<stes.length) {
+                       if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
+                               break;
+                       }
+                       startIx++;
+               }
+               // skip bottom frames (part of junit framework)
+               int endIx = startIx+1;
+               while(endIx < stes.length) {
+                       if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
+                               break;
+                       }
+                       endIx++;
+               }
+               if(startIx >= endIx) {
+                       // something went wrong. just print the whole stack trace
+                       e.printStackTrace(ps);
+               }
+               endIx -= 4; // skip 4 frames of reflection invocation
+               ps.println(e.toString());
+               for(int i=startIx; i<endIx; i++) {
+                       ps.println("\tat " + stes[i].toString());
+               }
+
+       }
+
+       private static String getRowCommentColumnValue(HSSFRow r) {
+               return getCellTextValue(r, SS.COLUMN_ROW_COMMENT, "row comment");
+       }
+
+       private static String getMarkerColumnValue(HSSFRow r) {
+               return getCellTextValue(r, SS.COLUMN_INDEX_MARKER, "marker");
+       }
+
+       /**
+        * @return <code>null</code> if cell is missing, empty or blank
+        */
+       private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) {
+               if(r == null) {
+                       return null;
+               }
+               HSSFCell cell = r.getCell(colIndex);
+               if(cell == null) {
+                       return null;
+               }
+               if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
+                       return null;
+               }
+               if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
+                       return cell.getRichStringCellValue().getString();
+               }
+
+               throw new RuntimeException("Bad cell type for '" + columnName + "' column: ("
+                               + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMatch.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMatch.java
new file mode 100644 (file)
index 0000000..f9fdab6
--- /dev/null
@@ -0,0 +1,205 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.NumericValueEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Test cases for MATCH()
+ *
+ * @author Josh Micich
+ */
+public final class TestMatch extends TestCase {
+       /** less than or equal to */
+       private static final NumberEval MATCH_LARGEST_LTE = new NumberEval(1);
+       private static final NumberEval MATCH_EXACT = new NumberEval(0);
+       /** greater than or equal to */
+       private static final NumberEval MATCH_SMALLEST_GTE = new NumberEval(-1);
+
+
+       private static ValueEval invokeMatch(ValueEval lookup_value, ValueEval lookup_array, ValueEval match_type) {
+               ValueEval[] args = { lookup_value, lookup_array, match_type, };
+               return new Match().evaluate(args, -1, (short)-1);
+       }
+       private static void confirmInt(int expected, ValueEval actualEval) {
+               if(!(actualEval instanceof NumericValueEval)) {
+                       fail("Expected numeric result");
+               }
+               NumericValueEval nve = (NumericValueEval)actualEval;
+               assertEquals(expected, nve.getNumberValue(), 0);
+       }
+
+       public void testSimpleNumber() {
+
+               ValueEval[] values = {
+                       new NumberEval(4),
+                       new NumberEval(5),
+                       new NumberEval(10),
+                       new NumberEval(10),
+                       new NumberEval(25),
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
+
+               confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE));
+               confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
+               confirmInt(4, invokeMatch(new NumberEval(10), ae, MATCH_LARGEST_LTE));
+               confirmInt(3, invokeMatch(new NumberEval(10), ae, MATCH_EXACT));
+               confirmInt(4, invokeMatch(new NumberEval(20), ae, MATCH_LARGEST_LTE));
+               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT));
+       }
+
+       public void testReversedNumber() {
+
+               ValueEval[] values = {
+                       new NumberEval(25),
+                       new NumberEval(10),
+                       new NumberEval(10),
+                       new NumberEval(10),
+                       new NumberEval(4),
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
+
+               confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_SMALLEST_GTE));
+               confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_EXACT));
+               confirmInt(4, invokeMatch(new NumberEval(9), ae, MATCH_SMALLEST_GTE));
+               confirmInt(1, invokeMatch(new NumberEval(20), ae, MATCH_SMALLEST_GTE));
+               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT));
+               assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(26), ae, MATCH_SMALLEST_GTE));
+       }
+
+       public void testSimpleString() {
+
+               ValueEval[] values = {
+                       new StringEval("Albert"),
+                       new StringEval("Charles"),
+                       new StringEval("Ed"),
+                       new StringEval("Greg"),
+                       new StringEval("Ian"),
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
+
+               // Note String comparisons are case insensitive
+               confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_LARGEST_LTE));
+               confirmInt(3, invokeMatch(new StringEval("eD"), ae, MATCH_LARGEST_LTE));
+               confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_EXACT));
+               confirmInt(3, invokeMatch(new StringEval("ed"), ae, MATCH_EXACT));
+               confirmInt(4, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
+               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
+       }
+
+       public void testSimpleBoolean() {
+
+               ValueEval[] values = {
+                               BoolEval.FALSE,
+                               BoolEval.FALSE,
+                               BoolEval.TRUE,
+                               BoolEval.TRUE,
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A4", values);
+
+               // Note String comparisons are case insensitive
+               confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE));
+               confirmInt(1, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT));
+               confirmInt(4, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE));
+               confirmInt(3, invokeMatch(BoolEval.TRUE, ae, MATCH_EXACT));
+       }
+
+       public void testHeterogeneous() {
+
+               ValueEval[] values = {
+                               new NumberEval(4),
+                               BoolEval.FALSE,
+                               new NumberEval(5),
+                               new StringEval("Albert"),
+                               BoolEval.FALSE,
+                               BoolEval.TRUE,
+                               new NumberEval(10),
+                               new StringEval("Charles"),
+                               new StringEval("Ed"),
+                               new NumberEval(10),
+                               new NumberEval(25),
+                               BoolEval.TRUE,
+                               new StringEval("Ed"),
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A13", values);
+
+               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Aaron"), ae, MATCH_LARGEST_LTE));
+
+               confirmInt(5, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE));
+               confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT));
+               confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE));
+               confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
+
+               confirmInt(8, invokeMatch(new StringEval("CHARLES"), ae, MATCH_EXACT));
+
+               confirmInt(4, invokeMatch(new StringEval("Ben"), ae, MATCH_LARGEST_LTE));
+
+               confirmInt(13, invokeMatch(new StringEval("ED"), ae, MATCH_LARGEST_LTE));
+               confirmInt(9, invokeMatch(new StringEval("ED"), ae, MATCH_EXACT));
+
+               confirmInt(13, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
+               assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
+
+               confirmInt(11, invokeMatch(new NumberEval(30), ae, MATCH_LARGEST_LTE));
+               confirmInt(12, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE));
+       }
+
+
+       /**
+        * Ensures that the match_type argument can be an <tt>AreaEval</tt>.<br/>
+        * Bugzilla 44421
+        */
+       public void testMatchArgTypeArea() {
+
+               ValueEval[] values = {
+                       new NumberEval(4),
+                       new NumberEval(5),
+                       new NumberEval(10),
+                       new NumberEval(10),
+                       new NumberEval(25),
+               };
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
+
+               AreaEval matchAE = EvalFactory.createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, });
+
+               try {
+                       confirmInt(4, invokeMatch(new NumberEval(10), ae, matchAE));
+               } catch (RuntimeException e) {
+                       if(e.getMessage().startsWith("Unexpected match_type type")) {
+                               // identified bug 44421
+                               fail(e.getMessage());
+                       }
+                       // some other error ??
+                       throw e;
+               }
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java
new file mode 100644 (file)
index 0000000..dd6974b
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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.
+*/
+/*
+ * Created on May 23, 2005
+ *
+ */
+package org.apache.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.functions.XYNumericFunction.Accumulator;
+
+
+/**
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ *  
+ */
+public class TestMathX extends AbstractNumericTestCase {
+
+    public void testAcosh() {
+        double d = 0;
+
+        d = MathX.acosh(0);
+        assertTrue("Acosh 0 is NaN", Double.isNaN(d));
+
+        d = MathX.acosh(1);
+        assertEquals("Acosh 1 ", 0, d);
+
+        d = MathX.acosh(-1);
+        assertTrue("Acosh -1 is NaN", Double.isNaN(d));
+
+        d = MathX.acosh(100);
+        assertEquals("Acosh 100 ", 5.298292366d, d);
+
+        d = MathX.acosh(101.001);
+        assertEquals("Acosh 101.001 ", 5.308253091d, d);
+
+        d = MathX.acosh(200000);
+        assertEquals("Acosh 200000 ", 12.89921983d, d);
+
+    }
+
+    public void testAsinh() {
+        double d = 0;
+
+        d = MathX.asinh(0);
+        assertEquals("asinh 0", d, 0);
+
+        d = MathX.asinh(1);
+        assertEquals("asinh 1 ", 0.881373587, d);
+
+        d = MathX.asinh(-1);
+        assertEquals("asinh -1 ", -0.881373587, d);
+
+        d = MathX.asinh(-100);
+        assertEquals("asinh -100 ", -5.298342366, d);
+
+        d = MathX.asinh(100);
+        assertEquals("asinh 100 ", 5.298342366, d);
+
+        d = MathX.asinh(200000);
+        assertEquals("asinh 200000", 12.899219826096400, d);
+
+        d = MathX.asinh(-200000);
+        assertEquals("asinh -200000 ", -12.899223853137, d);
+
+    }
+
+    public void testAtanh() {
+        double d = 0;
+        d = MathX.atanh(0);
+        assertEquals("atanh 0", d, 0);
+
+        d = MathX.atanh(1);
+        assertEquals("atanh 1 ", Double.POSITIVE_INFINITY, d);
+
+        d = MathX.atanh(-1);
+        assertEquals("atanh -1 ", Double.NEGATIVE_INFINITY, d);
+
+        d = MathX.atanh(-100);
+        assertEquals("atanh -100 ", Double.NaN, d);
+
+        d = MathX.atanh(100);
+        assertEquals("atanh 100 ", Double.NaN, d);
+
+        d = MathX.atanh(200000);
+        assertEquals("atanh 200000", Double.NaN, d);
+
+        d = MathX.atanh(-200000);
+        assertEquals("atanh -200000 ", Double.NaN, d);
+
+        d = MathX.atanh(0.1);
+        assertEquals("atanh 0.1", 0.100335348, d);
+
+        d = MathX.atanh(-0.1);
+        assertEquals("atanh -0.1 ", -0.100335348, d);
+
+    }
+
+    public void testCosh() {
+        double d = 0;
+        d = MathX.cosh(0);
+        assertEquals("cosh 0", 1, d);
+
+        d = MathX.cosh(1);
+        assertEquals("cosh 1 ", 1.543080635, d);
+
+        d = MathX.cosh(-1);
+        assertEquals("cosh -1 ", 1.543080635, d);
+
+        d = MathX.cosh(-100);
+        assertEquals("cosh -100 ", 1.344058570908070E+43, d);
+
+        d = MathX.cosh(100);
+        assertEquals("cosh 100 ", 1.344058570908070E+43, d);
+
+        d = MathX.cosh(15);
+        assertEquals("cosh 15", 1634508.686, d);
+
+        d = MathX.cosh(-15);
+        assertEquals("cosh -15 ", 1634508.686, d);
+
+        d = MathX.cosh(0.1);
+        assertEquals("cosh 0.1", 1.005004168, d);
+
+        d = MathX.cosh(-0.1);
+        assertEquals("cosh -0.1 ", 1.005004168, d);
+
+    }
+
+    public void testTanh() {
+        double d = 0;
+        d = MathX.tanh(0);
+        assertEquals("tanh 0", 0, d);
+
+        d = MathX.tanh(1);
+        assertEquals("tanh 1 ", 0.761594156, d);
+
+        d = MathX.tanh(-1);
+        assertEquals("tanh -1 ", -0.761594156, d);
+
+        d = MathX.tanh(-100);
+        assertEquals("tanh -100 ", -1, d);
+
+        d = MathX.tanh(100);
+        assertEquals("tanh 100 ", 1, d);
+
+        d = MathX.tanh(15);
+        assertEquals("tanh 15", 1, d);
+
+        d = MathX.tanh(-15);
+        assertEquals("tanh -15 ", -1, d);
+
+        d = MathX.tanh(0.1);
+        assertEquals("tanh 0.1", 0.099667995, d);
+
+        d = MathX.tanh(-0.1);
+        assertEquals("tanh -0.1 ", -0.099667995, d);
+
+    }
+
+    public void testMax() {
+        double[] d = new double[100];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        double m = MathX.max(d);
+        assertEquals("Max ", 20.1, m);
+        
+        d = new double[1000];
+        m = MathX.max(d);
+        assertEquals("Max ", 0, m);
+        
+        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
+        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
+        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
+        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
+        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
+        m = MathX.max(d);
+        assertEquals("Max ", 20.1, m);
+        
+        d = new double[20];
+        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
+        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
+        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
+        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
+        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
+        m = MathX.max(d);
+        assertEquals("Max ", -1.1, m);
+        
+    }
+
+    public void testMin() {
+        double[] d = new double[100];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        double m = MathX.min(d);
+        assertEquals("Min ", 0, m);
+        
+        d = new double[20];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        m = MathX.min(d);
+        assertEquals("Min ", 1.1, m);
+        
+        d = new double[1000];
+        m = MathX.min(d);
+        assertEquals("Min ", 0, m);
+        
+        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
+        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
+        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
+        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
+        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
+        m = MathX.min(d);
+        assertEquals("Min ", -19.1, m);
+        
+        d = new double[20];
+        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
+        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
+        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
+        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
+        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
+        m = MathX.min(d);
+        assertEquals("Min ", -20.1, m);
+    }
+
+    public void testProduct() {
+        double[] d = new double[100];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        double m = MathX.min(d);
+        assertEquals("Min ", 0, m);
+        
+        d = new double[20];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        m = MathX.min(d);
+        assertEquals("Min ", 1.1, m);
+        
+        d = new double[1000];
+        m = MathX.min(d);
+        assertEquals("Min ", 0, m);
+        
+        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
+        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
+        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
+        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
+        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
+        m = MathX.min(d);
+        assertEquals("Min ", -19.1, m);
+        
+        d = new double[20];
+        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
+        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
+        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
+        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
+        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
+        m = MathX.min(d);
+        assertEquals("Min ", -20.1, m);
+    }
+
+    public void testMod() {
+
+        //example from Excel help
+        assertEquals(1.0, MathX.mod(3, 2));
+        assertEquals(1.0, MathX.mod(-3, 2));
+        assertEquals(-1.0, MathX.mod(3, -2));
+        assertEquals(-1.0, MathX.mod(-3, -2));
+
+        assertEquals((double) 1.4, MathX.mod(3.4, 2));
+        assertEquals((double) -1.4, MathX.mod(-3.4, -2));
+        assertEquals((double) 0.6000000000000001, MathX.mod(-3.4, 2.0));// should actually be 0.6
+        assertEquals((double) -0.6000000000000001, MathX.mod(3.4, -2.0));// should actually be -0.6
+
+        // Bugzilla 50033
+        assertEquals(1.0, MathX.mod(13, 12));
+    }
+
+    public void testNChooseK() {
+        int n=100;
+        int k=50;
+        double d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 1.00891344545564E29, d);
+        
+        n = -1; k = 1;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", Double.NaN, d);
+        
+        n = 1; k = -1;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", Double.NaN, d);
+        
+        n = 0; k = 1;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", Double.NaN, d);
+        
+        n = 1; k = 0;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 1, d);
+        
+        n = 10; k = 9;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 10, d);
+        
+        n = 10; k = 10;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 1, d);
+        
+        n = 10; k = 1;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 10, d);
+        
+        n = 1000; k = 1;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 1000, d); // awesome ;)
+        
+        n = 1000; k = 2;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 499500, d); // awesome ;)
+        
+        n = 13; k = 7;
+        d = MathX.nChooseK(n, k);
+        assertEquals("NChooseK ", 1716, d);
+        
+    }
+
+    public void testSign() {
+        final short minus = -1;
+        final short zero = 0;
+        final short plus = 1;
+        double d = 0;
+        
+        
+        assertEquals("Sign ", minus, MathX.sign(minus));
+        assertEquals("Sign ", plus, MathX.sign(plus));
+        assertEquals("Sign ", zero, MathX.sign(zero));
+        
+        d = 0;
+        assertEquals("Sign ", zero, MathX.sign(d));
+        
+        d = -1.000001;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = -.000001;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = -1E-200;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = Double.NEGATIVE_INFINITY;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = -200.11;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = -2000000000000.11;
+        assertEquals("Sign ", minus, MathX.sign(d));
+        
+        d = 1.000001;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+        d = .000001;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+        d = 1E-200;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+        d = Double.POSITIVE_INFINITY;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+        d = 200.11;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+        d = 2000000000000.11;
+        assertEquals("Sign ", plus, MathX.sign(d));
+        
+    }
+
+    public void testSinh() {
+        double d = 0;
+        d = MathX.sinh(0);
+        assertEquals("sinh 0", 0, d);
+
+        d = MathX.sinh(1);
+        assertEquals("sinh 1 ", 1.175201194, d);
+
+        d = MathX.sinh(-1);
+        assertEquals("sinh -1 ", -1.175201194, d);
+
+        d = MathX.sinh(-100);
+        assertEquals("sinh -100 ", -1.344058570908070E+43, d);
+
+        d = MathX.sinh(100);
+        assertEquals("sinh 100 ", 1.344058570908070E+43, d);
+
+        d = MathX.sinh(15);
+        assertEquals("sinh 15", 1634508.686, d);
+
+        d = MathX.sinh(-15);
+        assertEquals("sinh -15 ", -1634508.686, d);
+
+        d = MathX.sinh(0.1);
+        assertEquals("sinh 0.1", 0.10016675, d);
+
+        d = MathX.sinh(-0.1);
+        assertEquals("sinh -0.1 ", -0.10016675, d);
+
+    }
+
+    public void testSum() {
+        double[] d = new double[100];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        double s = MathX.sum(d);
+        assertEquals("Sum ", 212, s);
+        
+        d = new double[1000];
+        s = MathX.sum(d);
+        assertEquals("Sum ", 0, s);
+        
+        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
+        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
+        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
+        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
+        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
+        s = MathX.sum(d);
+        assertEquals("Sum ", 10, s);
+        
+        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
+        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
+        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
+        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
+        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
+        s = MathX.sum(d);
+        assertEquals("Sum ", -212, s);
+        
+    }
+
+    public void testSumsq() {
+        double[] d = new double[100];
+        d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
+        d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
+        d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
+        d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
+        d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
+        
+        double s = MathX.sumsq(d);
+        assertEquals("Sumsq ", 2912.2, s);
+        
+        d = new double[1000];
+        s = MathX.sumsq(d);
+        assertEquals("Sumsq ", 0, s);
+        
+        d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
+        d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
+        d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
+        d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
+        d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
+        s = MathX.sumsq(d);
+        assertEquals("Sumsq ", 2912.2, s);
+        
+        d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
+        d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
+        d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
+        d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
+        d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
+        s = MathX.sumsq(d);
+        assertEquals("Sumsq ", 2912.2, s);
+    }
+
+    public void testFactorial() {
+        int n = 0;
+        double s = 0;
+        
+        n = 0;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", 1, s);
+        
+        n = 1;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", 1, s);
+        
+        n = 10;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", 3628800, s);
+        
+        n = 99;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", 9.33262154439E+155, s);
+        
+        n = -1;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", Double.NaN, s);
+        
+        n = Integer.MAX_VALUE;
+        s = MathX.factorial(n);
+        assertEquals("Factorial ", Double.POSITIVE_INFINITY, s);
+    }
+
+    public void testSumx2my2() {
+        double[] xarr = null;
+        double[] yarr = null;
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumx2my2(xarr, yarr, 100);
+        
+        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumx2my2(xarr, yarr, 100);
+        
+        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumx2my2(xarr, yarr, -100);
+        
+        xarr = new double[]{10};
+        yarr = new double[]{9};
+        confirmSumx2my2(xarr, yarr, 19);
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumx2my2(xarr, yarr, 0);
+    }
+
+    public void testSumx2py2() {
+        double[] xarr = null;
+        double[] yarr = null;
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumx2py2(xarr, yarr, 670);
+        
+        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumx2py2(xarr, yarr, 670);
+        
+        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumx2py2(xarr, yarr, 670);
+        
+        xarr = new double[]{10};
+        yarr = new double[]{9};
+        confirmSumx2py2(xarr, yarr, 181);
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumx2py2(xarr, yarr, 770);
+    }
+
+    public void testSumxmy2() {
+        double[] xarr = null;
+        double[] yarr = null;
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumxmy2(xarr, yarr, 10);
+        
+        xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+        yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        confirmSumxmy2(xarr, yarr, 1330);
+        
+        xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumxmy2(xarr, yarr, 10);
+        
+        xarr = new double[]{10};
+        yarr = new double[]{9};
+        confirmSumxmy2(xarr, yarr, 1);
+        
+        xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        confirmSumxmy2(xarr, yarr, 0);
+    }
+
+    private static void confirmSumx2my2(double[] xarr, double[] yarr, double expectedResult) {
+        confirmXY(new Sumx2my2().createAccumulator(), xarr, yarr, expectedResult);
+    }
+    private static void confirmSumx2py2(double[] xarr, double[] yarr, double expectedResult) {
+        confirmXY(new Sumx2py2().createAccumulator(), xarr, yarr, expectedResult);
+    }
+    private static void confirmSumxmy2(double[] xarr, double[] yarr, double expectedResult) {
+        confirmXY(new Sumxmy2().createAccumulator(), xarr, yarr, expectedResult);
+    }
+
+    private static void confirmXY(Accumulator acc, double[] xarr, double[] yarr,
+            double expectedResult) {
+        double result = 0.0;
+        for (int i = 0; i < xarr.length; i++) {
+            result += acc.accumulate(xarr[i], yarr[i]);
+        }
+        assertEquals(expectedResult, result, 0.0);
+    }
+    
+    public void testRound() {
+        double d = 0;
+        int p = 0;
+        
+        d = 0; p = 0;
+        assertEquals("round ", 0, MathX.round(d, p));
+        
+        d = 10; p = 0;
+        assertEquals("round ", 10, MathX.round(d, p));
+        
+        d = 123.23; p = 0;
+        assertEquals("round ", 123, MathX.round(d, p));
+        
+        d = -123.23; p = 0;
+        assertEquals("round ", -123, MathX.round(d, p));
+        
+        d = 123.12; p = 2;
+        assertEquals("round ", 123.12, MathX.round(d, p));
+        
+        d = 88.123459; p = 5;
+        assertEquals("round ", 88.12346, MathX.round(d, p));
+        
+        d = 0; p = 2;
+        assertEquals("round ", 0, MathX.round(d, p));
+        
+        d = 0; p = -1;
+        assertEquals("round ", 0, MathX.round(d, p));
+        
+        d = 0.01; p = -1;
+        assertEquals("round ", 0, MathX.round(d, p));
+
+        d = 123.12; p = -2;
+        assertEquals("round ", 100, MathX.round(d, p));
+        
+        d = 88.123459; p = -3;
+        assertEquals("round ", 0, MathX.round(d, p));
+        
+        d = 49.00000001; p = -1;
+        assertEquals("round ", 50, MathX.round(d, p));
+        
+        d = 149.999999; p = -2;
+        assertEquals("round ", 100, MathX.round(d, p));
+        
+        d = 150.0; p = -2;
+        assertEquals("round ", 200, MathX.round(d, p));
+    }
+
+    public void testRoundDown() {
+        double d = 0;
+        int p = 0;
+        
+        d = 0; p = 0;
+        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
+        
+        d = 10; p = 0;
+        assertEquals("roundDown ", 10, MathX.roundDown(d, p));
+        
+        d = 123.99; p = 0;
+        assertEquals("roundDown ", 123, MathX.roundDown(d, p));
+        
+        d = -123.99; p = 0;
+        assertEquals("roundDown ", -123, MathX.roundDown(d, p));
+        
+        d = 123.99; p = 2;
+        assertEquals("roundDown ", 123.99, MathX.roundDown(d, p));
+        
+        d = 88.123459; p = 5;
+        assertEquals("roundDown ", 88.12345, MathX.roundDown(d, p));
+        
+        d = 0; p = 2;
+        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
+        
+        d = 0; p = -1;
+        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
+        
+        d = 0.01; p = -1;
+        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
+
+        d = 199.12; p = -2;
+        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
+        
+        d = 88.123459; p = -3;
+        assertEquals("roundDown ", 0, MathX.roundDown(d, p));
+        
+        d = 99.00000001; p = -1;
+        assertEquals("roundDown ", 90, MathX.roundDown(d, p));
+        
+        d = 100.00001; p = -2;
+        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
+        
+        d = 150.0; p = -2;
+        assertEquals("roundDown ", 100, MathX.roundDown(d, p));
+    }
+
+    public void testRoundUp() {
+        double d = 0;
+        int p = 0;
+        
+        d = 0; p = 0;
+        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
+        
+        d = 10; p = 0;
+        assertEquals("roundUp ", 10, MathX.roundUp(d, p));
+        
+        d = 123.23; p = 0;
+        assertEquals("roundUp ", 124, MathX.roundUp(d, p));
+        
+        d = -123.23; p = 0;
+        assertEquals("roundUp ", -124, MathX.roundUp(d, p));
+        
+        d = 123.12; p = 2;
+        assertEquals("roundUp ", 123.12, MathX.roundUp(d, p));
+        
+        d = 88.123459; p = 5;
+        assertEquals("roundUp ", 88.12346, MathX.roundUp(d, p));
+        
+        d = 0; p = 2;
+        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
+        
+        d = 0; p = -1;
+        assertEquals("roundUp ", 0, MathX.roundUp(d, p));
+        
+        d = 0.01; p = -1;
+        assertEquals("roundUp ", 10, MathX.roundUp(d, p));
+
+        d = 123.12; p = -2;
+        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
+        
+        d = 88.123459; p = -3;
+        assertEquals("roundUp ", 1000, MathX.roundUp(d, p));
+        
+        d = 49.00000001; p = -1;
+        assertEquals("roundUp ", 50, MathX.roundUp(d, p));
+        
+        d = 149.999999; p = -2;
+        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
+        
+        d = 150.0; p = -2;
+        assertEquals("roundUp ", 200, MathX.roundUp(d, p));
+    }
+
+    public void testCeiling() {
+        double d = 0;
+        double s = 0;
+        
+        d = 0; s = 0;
+        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
+        
+        d = 1; s = 0;
+        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
+        
+        d = 0; s = 1;
+        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
+        
+        d = -1; s = 0;
+        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
+        
+        d = 0; s = -1;
+        assertEquals("ceiling ", 0, MathX.ceiling(d, s));
+        
+        d = 10; s = 1.11;
+        assertEquals("ceiling ", 11.1, MathX.ceiling(d, s));
+        
+        d = 11.12333; s = 0.03499;
+        assertEquals("ceiling ", 11.12682, MathX.ceiling(d, s));
+        
+        d = -11.12333; s = 0.03499;
+        assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
+        
+        d = 11.12333; s = -0.03499;
+        assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
+        
+        d = -11.12333; s = -0.03499;
+        assertEquals("ceiling ", -11.12682, MathX.ceiling(d, s));
+        
+        d = 100; s = 0.001;
+        assertEquals("ceiling ", 100, MathX.ceiling(d, s));
+        
+        d = -0.001; s = -9.99;
+        assertEquals("ceiling ", -9.99, MathX.ceiling(d, s));
+        
+        d = 4.42; s = 0.05;
+        assertEquals("ceiling ", 4.45, MathX.ceiling(d, s));
+        
+        d = 0.05; s = 4.42;
+        assertEquals("ceiling ", 4.42, MathX.ceiling(d, s));
+        
+        d = 0.6666; s = 3.33;
+        assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
+        
+        d = 2d/3; s = 3.33;
+        assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
+    }
+
+    public void testFloor() {
+        double d = 0;
+        double s = 0;
+        
+        d = 0; s = 0;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = 1; s = 0;
+        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
+        
+        d = 0; s = 1;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = -1; s = 0;
+        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
+        
+        d = 0; s = -1;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = 10; s = 1.11;
+        assertEquals("floor ", 9.99, MathX.floor(d, s));
+        
+        d = 11.12333; s = 0.03499;
+        assertEquals("floor ", 11.09183, MathX.floor(d, s));
+        
+        d = -11.12333; s = 0.03499;
+        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
+        
+        d = 11.12333; s = -0.03499;
+        assertEquals("floor ", Double.NaN, MathX.floor(d, s));
+        
+        d = -11.12333; s = -0.03499;
+        assertEquals("floor ", -11.09183, MathX.floor(d, s));
+        
+        d = 100; s = 0.001;
+        assertEquals("floor ", 100, MathX.floor(d, s));
+        
+        d = -0.001; s = -9.99;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = 4.42; s = 0.05;
+        assertEquals("floor ", 4.4, MathX.floor(d, s));
+        
+        d = 0.05; s = 4.42;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = 0.6666; s = 3.33;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+        
+        d = 2d/3; s = 3.33;
+        assertEquals("floor ", 0, MathX.floor(d, s));
+    }
+
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMid.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMid.java
new file mode 100644 (file)
index 0000000..7c19d44
--- /dev/null
@@ -0,0 +1,110 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.RefEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+/**
+ * Tests for Excel function MID()
+ *
+ * @author Josh Micich
+ */
+public final class TestMid extends TestCase {
+
+
+       private static ValueEval invokeMid(ValueEval text, ValueEval startPos, ValueEval numChars) {
+               ValueEval[] args = new ValueEval[] { text, startPos, numChars, };
+               return TextFunction.MID.evaluate(args, -1, (short)-1);
+       }
+
+       private void confirmMid(ValueEval text, ValueEval startPos, ValueEval numChars, String expected) {
+               ValueEval result = invokeMid(text, startPos, numChars);
+               assertEquals(StringEval.class, result.getClass());
+               assertEquals(expected, ((StringEval)result).getStringValue());
+       }
+
+       private void confirmMid(ValueEval text, ValueEval startPos, ValueEval numChars, ErrorEval expectedError) {
+               ValueEval result = invokeMid(text, startPos, numChars);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
+       }
+
+       public void testBasic() {
+
+               confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(4), "lact");
+       }
+
+       /**
+        * Valid cases where args are not precisely (string, int, int) but can be resolved OK.
+        */
+       public void testUnusualArgs() {
+               // startPos with fractional digits
+               confirmMid(new StringEval("galactic"), new NumberEval(3.1), new NumberEval(4), "lact");
+
+               // string startPos
+               confirmMid(new StringEval("galactic"), new StringEval("3"), new NumberEval(4), "lact");
+
+               // text (first) arg type is number, other args are strings with fractional digits
+               confirmMid(new NumberEval(123456), new StringEval("3.1"), new StringEval("2.9"), "34");
+
+               // startPos is 1x1 area ref, numChars is cell ref
+               AreaEval aeStart = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(2), } );
+               RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3));
+               confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala");
+
+               confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.instance, "");
+
+               confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.FALSE, "");
+               confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.TRUE, "l");
+               confirmMid(BlankEval.instance, new NumberEval(3), BoolEval.TRUE, "");
+
+       }
+
+       /**
+        * Extreme values for startPos and numChars
+        */
+       public void testExtremes() {
+               confirmMid(new StringEval("galactic"), new NumberEval(4), new NumberEval(400), "actic");
+
+               confirmMid(new StringEval("galactic"), new NumberEval(30), new NumberEval(4), "");
+               confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(0), "");
+       }
+
+       /**
+        * All sorts of ways to make MID return defined errors.
+        */
+       public void testErrors() {
+               confirmMid(ErrorEval.NAME_INVALID, new NumberEval(3), new NumberEval(4), ErrorEval.NAME_INVALID);
+               confirmMid(new StringEval("galactic"), ErrorEval.NAME_INVALID, new NumberEval(4), ErrorEval.NAME_INVALID);
+               confirmMid(new StringEval("galactic"), new NumberEval(3), ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
+               confirmMid(new StringEval("galactic"), ErrorEval.DIV_ZERO, ErrorEval.NAME_INVALID, ErrorEval.DIV_ZERO);
+
+               confirmMid(new StringEval("galactic"), BlankEval.instance, new NumberEval(3.1), ErrorEval.VALUE_INVALID);
+
+               confirmMid(new StringEval("galactic"), new NumberEval(0), new NumberEval(4), ErrorEval.VALUE_INVALID);
+               confirmMid(new StringEval("galactic"), new NumberEval(1), new NumberEval(-1), ErrorEval.VALUE_INVALID);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestNper.java b/src/testcases/org/apache/poi/ss/formula/functions/TestNper.java
new file mode 100644 (file)
index 0000000..4754ec0
--- /dev/null
@@ -0,0 +1,65 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Tests for {@link FinanceFunction#NPER}
+ *
+ * @author Josh Micich
+ */
+public final class TestNper extends TestCase {
+       public void testSimpleEvaluate() {
+
+               ValueEval[] args = {
+                       new NumberEval(0.05),
+                       new NumberEval(250),
+                       new NumberEval(-1000),
+               };
+               ValueEval result = FinanceFunction.NPER.evaluate(args, 0, (short)0);
+
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(4.57353557, ((NumberEval)result).getNumberValue(), 0.00000001);
+       }
+
+       public void testEvaluate_bug_45732() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("Sheet1");
+               HSSFCell cell = sheet.createRow(0).createCell(0);
+
+               cell.setCellFormula("NPER(12,4500,100000,100000)");
+               cell.setCellValue(15.0);
+               assertEquals("NPER(12,4500,100000,100000)", cell.getCellFormula());
+               assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
+               assertEquals(15.0, cell.getNumericCellValue(), 0.0);
+
+               HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+               fe.evaluateFormulaCell(cell);
+               assertEquals(HSSFCell.CELL_TYPE_ERROR, cell.getCachedFormulaResultType());
+               assertEquals(HSSFErrorConstants.ERROR_NUM, cell.getErrorCellValue());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestOffset.java b/src/testcases/org/apache/poi/ss/formula/functions/TestOffset.java
new file mode 100644 (file)
index 0000000..24d3472
--- /dev/null
@@ -0,0 +1,99 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.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) {
+               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);
+               confirmDoubleConvert(+1.01, +1);
+               confirmDoubleConvert(+1.00, +1);
+               confirmDoubleConvert(+0.99,  0);
+               confirmDoubleConvert(+0.01,  0);
+               confirmDoubleConvert( 0.00,  0);
+               confirmDoubleConvert(-0.01, -1);
+               confirmDoubleConvert(-0.99, -1);
+               confirmDoubleConvert(-1.00, -1);
+               confirmDoubleConvert(-1.01, -2);
+               confirmDoubleConvert(-1.99, -2);
+               confirmDoubleConvert(-2.00, -2);
+               confirmDoubleConvert(-2.01, -3);
+       }
+
+       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));
+               lor = lor.normaliseAndTranslate(16300);
+               assertTrue(lor.isOutOfBounds(0, 16383));
+               assertFalse(lor.isOutOfBounds(0, 65535));
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestPmt.java b/src/testcases/org/apache/poi/ss/formula/functions/TestPmt.java
new file mode 100644 (file)
index 0000000..7761880
--- /dev/null
@@ -0,0 +1,86 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+
+/**
+ * @author Josh Micich
+ */
+public final class TestPmt extends TestCase {
+
+       private static void confirm(double expected, NumberEval ne) {
+               // only asserting accuracy to 4 fractional digits
+               assertEquals(expected, ne.getNumberValue(), 0.00005);
+       }
+       private static ValueEval invoke(ValueEval[] args) {
+               return FinanceFunction.PMT.evaluate(args, -1, (short)-1);
+       }
+       /**
+        * Invocation when not expecting an error result
+        */
+       private static NumberEval invokeNormal(ValueEval[] args) {
+               ValueEval ev = invoke(args);
+               if(ev instanceof ErrorEval) {
+                       throw new AssertionFailedError("Normal evaluation failed with error code: "
+                                       + ev.toString());
+               }
+               return (NumberEval) ev;
+       }
+
+       private static void confirm(double expected, double rate, double nper, double pv, double fv, boolean isBeginning) {
+               ValueEval[] args = {
+                               new NumberEval(rate),
+                               new NumberEval(nper),
+                               new NumberEval(pv),
+                               new NumberEval(fv),
+                               new NumberEval(isBeginning ? 1 : 0),
+               };
+               confirm(expected, invokeNormal(args));
+       }
+
+
+       public void testBasic() {
+               confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
+               confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
+       }
+
+       public void test3args() {
+
+               ValueEval[] args = {
+                               new NumberEval(0.005),
+                               new NumberEval(24),
+                               new NumberEval(1000),
+               };
+               ValueEval ev = invoke(args);
+               if(ev instanceof ErrorEval) {
+                       ErrorEval err = (ErrorEval) ev;
+                       if(err.getErrorCode() == HSSFErrorConstants.ERROR_VALUE) {
+                               throw new AssertionFailedError("Identified bug 44691");
+                       }
+               }
+
+               confirm(-44.3206, invokeNormal(args));
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestPoisson.java b/src/testcases/org/apache/poi/ss/formula/functions/TestPoisson.java
new file mode 100644 (file)
index 0000000..e18d66e
--- /dev/null
@@ -0,0 +1,111 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Tests for Excel function POISSON(x,mean,cumulative)
+ * @author Kalpesh Parmar
+ */
+public class TestPoisson extends TestCase {
+
+    private static final double DELTA = 1E-15;
+
+    private static ValueEval invokePoisson(double x, double mean, boolean cumulative)
+    {
+
+        ValueEval[] valueEvals = new ValueEval[3];
+        valueEvals[0] = new NumberEval(x);
+        valueEvals[1] = new NumberEval(mean);
+        valueEvals[2] = BoolEval.valueOf(cumulative);
+
+        return NumericFunction.POISSON.evaluate(valueEvals,-1,-1);
+       }
+
+    public void testCumulativeProbability()
+    {
+        double x = 1;
+        double mean = 0.2;
+        double result = 0.9824769036935787; // known result
+
+        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
+
+        assertEquals(myResult.getNumberValue(), result, DELTA);
+    }
+
+    public void testNonCumulativeProbability()
+    {
+        double x = 0;
+        double mean = 0.2;
+        double result = 0.8187307530779818; // known result
+        
+        NumberEval myResult = (NumberEval)invokePoisson(x,mean,false);
+
+        assertEquals(myResult.getNumberValue(), result, DELTA);
+    }
+
+    public void testNegativeMean()
+    {
+        double x = 0;
+        double mean = -0.2;
+
+        ErrorEval myResult = (ErrorEval)invokePoisson(x,mean,false);
+
+        assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), myResult.getErrorCode());
+    }
+
+    public void testNegativeX()
+    {
+        double x = -1;
+        double mean = 0.2;
+
+        ErrorEval myResult = (ErrorEval)invokePoisson(x,mean,false);
+
+        assertEquals(ErrorEval.NUM_ERROR.getErrorCode(), myResult.getErrorCode());    
+    }
+
+
+
+    public void testXAsDecimalNumber()
+    {
+        double x = 1.1;
+        double mean = 0.2;
+        double result = 0.9824769036935787; // known result
+
+        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
+
+        assertEquals(myResult.getNumberValue(), result, DELTA);
+    }
+
+    public void testXZeroMeanZero()
+    {
+        double x = 0;
+        double mean = 0;
+        double result = 1; // known result in excel
+
+        NumberEval myResult = (NumberEval)invokePoisson(x,mean,true);
+
+        assertEquals(myResult.getNumberValue(), result, DELTA);
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestRoundFuncs.java b/src/testcases/org/apache/poi/ss/formula/functions/TestRoundFuncs.java
new file mode 100644 (file)
index 0000000..10166ee
--- /dev/null
@@ -0,0 +1,50 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+
+/**
+ * Test cases for ROUND(), ROUNDUP(), ROUNDDOWN()
+ *
+ * @author Josh Micich
+ */
+public final class TestRoundFuncs extends TestCase {
+       private static final NumericFunction F = null;
+       public void testRounddownWithStringArg() {
+
+               ValueEval strArg = new StringEval("abc");
+               ValueEval[] args = { strArg, new NumberEval(2), };
+               ValueEval result = F.ROUNDDOWN.evaluate(args, -1, (short)-1);
+               assertEquals(ErrorEval.VALUE_INVALID, result);
+       }
+
+       public void testRoundupWithStringArg() {
+
+               ValueEval strArg = new StringEval("abc");
+               ValueEval[] args = { strArg, new NumberEval(2), };
+               ValueEval result = F.ROUNDUP.evaluate(args, -1, (short)-1);
+               assertEquals(ErrorEval.VALUE_INVALID, result);
+       }
+
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestRowCol.java b/src/testcases/org/apache/poi/ss/formula/functions/TestRowCol.java
new file mode 100644 (file)
index 0000000..a27a63e
--- /dev/null
@@ -0,0 +1,97 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Tests for ROW(), ROWS(), COLUMN(), COLUMNS()
+ *
+ * @author Josh Micich
+ */
+public final class TestRowCol extends TestCase {
+
+       public void testCol() {
+               Function target = new Column();
+               {
+                       ValueEval[] args = { EvalFactory.createRefEval("C5"), };
+                       double actual = NumericFunctionInvoker.invoke(target, args);
+                       assertEquals(3, actual, 0D);
+               }
+               {
+                       ValueEval[] args = { EvalFactory.createAreaEval("E2:H12", new ValueEval[44]), };
+                       double actual = NumericFunctionInvoker.invoke(target, args);
+                       assertEquals(5, actual, 0D);
+               }
+       }
+
+       public void testRow() {
+               Function target = new RowFunc();
+               {
+                       ValueEval[] args = { EvalFactory.createRefEval("C5"), };
+                       double actual = NumericFunctionInvoker.invoke(target, args);
+                       assertEquals(5, actual, 0D);
+               }
+               {
+                       ValueEval[] args = { EvalFactory.createAreaEval("E2:H12", new ValueEval[44]), };
+                       double actual = NumericFunctionInvoker.invoke(target, args);
+                       assertEquals(2, actual, 0D);
+               }
+       }
+
+       public void testColumns() {
+
+               confirmColumnsFunc("A1:F1", 6, 1);
+               confirmColumnsFunc("A1:C2", 3, 2);
+               confirmColumnsFunc("A1:B3", 2, 3);
+               confirmColumnsFunc("A1:A6", 1, 6);
+
+               ValueEval[] args = { EvalFactory.createRefEval("C5"), };
+               double actual = NumericFunctionInvoker.invoke(new Columns(), args);
+               assertEquals(1, actual, 0D);
+       }
+
+       public void testRows() {
+
+               confirmRowsFunc("A1:F1", 6, 1);
+               confirmRowsFunc("A1:C2", 3, 2);
+               confirmRowsFunc("A1:B3", 2, 3);
+               confirmRowsFunc("A1:A6", 1, 6);
+
+               ValueEval[] args = { EvalFactory.createRefEval("C5"), };
+               double actual = NumericFunctionInvoker.invoke(new Rows(), args);
+               assertEquals(1, actual, 0D);
+       }
+
+       private static void confirmRowsFunc(String areaRefStr, int nCols, int nRows) {
+               ValueEval[] args = { EvalFactory.createAreaEval(areaRefStr, new ValueEval[nCols * nRows]), };
+
+               double actual = NumericFunctionInvoker.invoke(new Rows(), args);
+               assertEquals(nRows, actual, 0D);
+       }
+
+
+       private static void confirmColumnsFunc(String areaRefStr, int nCols, int nRows) {
+               ValueEval[] args = { EvalFactory.createAreaEval(areaRefStr, new ValueEval[nCols * nRows]), };
+
+               double actual = NumericFunctionInvoker.invoke(new Columns(), args);
+               assertEquals(nCols, actual, 0D);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestStatsLib.java b/src/testcases/org/apache/poi/ss/formula/functions/TestStatsLib.java
new file mode 100644 (file)
index 0000000..47ce2d5
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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.
+*/
+/*
+ * Created on May 30, 2005
+ *
+ */
+package org.apache.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+
+
+/**
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ *
+ */
+public class TestStatsLib extends AbstractNumericTestCase {
+
+    public void testDevsq() {
+        double[] v = null;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        d = StatsLib.devsq(v);
+        x = 82.5;
+        assertEquals("devsq ", x, d);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        d = StatsLib.devsq(v);
+        x = 0;
+        assertEquals("devsq ", x, d);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        d = StatsLib.devsq(v);
+        x = 0;
+        assertEquals("devsq ", x, d);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        d = StatsLib.devsq(v);
+        x = 2.5;
+        assertEquals("devsq ", x, d);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        d = StatsLib.devsq(v);
+        x = 10953.7416965767;
+        assertEquals("devsq ", x, d);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.devsq(v);
+        x = 82.5;
+        assertEquals("devsq ", x, d);
+    }
+
+    public void testKthLargest() {
+        double[] v = null;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        d = StatsLib.kthLargest(v, 3);
+        x = 8;
+        assertEquals("kthLargest ", x, d);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        d = StatsLib.kthLargest(v, 3);
+        x = 1;
+        assertEquals("kthLargest ", x, d);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        d = StatsLib.kthLargest(v, 3);
+        x = 0;
+        assertEquals("kthLargest ", x, d);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        d = StatsLib.kthLargest(v, 3);
+        x = 2;
+        assertEquals("kthLargest ", x, d);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        d = StatsLib.kthLargest(v, 3);
+        x = 5.37828;
+        assertEquals("kthLargest ", x, d);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.kthLargest(v, 3);
+        x = -3;
+        assertEquals("kthLargest ", x, d);
+    }
+
+    public void testKthSmallest() {
+    }
+
+    public void testAvedev() {
+        double[] v = null;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        d = StatsLib.avedev(v);
+        x = 2.5;
+        assertEquals("avedev ", x, d);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        d = StatsLib.avedev(v);
+        x = 0;
+        assertEquals("avedev ", x, d);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        d = StatsLib.avedev(v);
+        x = 0;
+        assertEquals("avedev ", x, d);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        d = StatsLib.avedev(v);
+        x = 0.5;
+        assertEquals("avedev ", x, d);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        d = StatsLib.avedev(v);
+        x = 36.42176053333;
+        assertEquals("avedev ", x, d);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.avedev(v);
+        x = 2.5;
+        assertEquals("avedev ", x, d);
+    }
+
+    public void testMedian() {
+        double[] v = null;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        d = StatsLib.median(v);
+        x = 5.5;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        d = StatsLib.median(v);
+        x = 1;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        d = StatsLib.median(v);
+        x = 0;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        d = StatsLib.median(v);
+        x = 1.5;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        d = StatsLib.median(v);
+        x = 5.37828;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.median(v);
+        x = -5.5;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.median(v);
+        x = -6;
+        assertEquals("median ", x, d);
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9};
+        d = StatsLib.median(v);
+        x = 5;
+        assertEquals("median ", x, d);
+    }
+
+    public void testMode() {
+        double[] v;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        confirmMode(v, null);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        confirmMode(v, 1.0);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        confirmMode(v, 0.0);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        confirmMode(v, 1.0);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        confirmMode(v, null);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        confirmMode(v, null);
+        
+        v = new double[] {1,2,3,4,1,1,1,1,0,0,0,0,0};
+        confirmMode(v, 1.0);
+        
+        v = new double[] {0,1,2,3,4,1,1,1,0,0,0,0,1};
+        confirmMode(v, 0.0);
+    }
+    private static void confirmMode(double[] v, double expectedResult) {
+       confirmMode(v, new Double(expectedResult));
+    }
+    private static void confirmMode(double[] v, Double expectedResult) {
+       double actual;
+               try {
+                       actual = Mode.evaluate(v);
+                       if (expectedResult == null) {
+                               throw new AssertionFailedError("Expected N/A exception was not thrown");
+                       }
+               } catch (EvaluationException e) {
+                       if (expectedResult == null) {
+                               assertEquals(ErrorEval.NA, e.getErrorEval());
+                               return;
+                       }
+                       throw new RuntimeException(e);
+               }
+       assertEquals("mode", expectedResult.doubleValue(), actual);
+    }
+    
+
+    public void testStddev() {
+        double[] v = null;
+        double d, x = 0;
+        
+        v = new double[] {1,2,3,4,5,6,7,8,9,10};
+        d = StatsLib.stdev(v);
+        x = 3.02765035410;
+        assertEquals("stdev ", x, d);
+        
+        v = new double[] {1,1,1,1,1,1,1,1,1,1};
+        d = StatsLib.stdev(v);
+        x = 0;
+        assertEquals("stdev ", x, d);
+        
+        v = new double[] {0,0,0,0,0,0,0,0,0,0};
+        d = StatsLib.stdev(v);
+        x = 0;
+        assertEquals("stdev ", x, d);
+        
+        v = new double[] {1,2,1,2,1,2,1,2,1,2};
+        d = StatsLib.stdev(v);
+        x = 0.52704627669;
+        assertEquals("stdev ", x, d);
+        
+        v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
+        d = StatsLib.stdev(v);
+        x = 52.33006233652;
+        assertEquals("stdev ", x, d);
+        
+        v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
+        d = StatsLib.stdev(v);
+        x = 3.02765035410;
+        assertEquals("stdev ", x, d);
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestSubtotal.java b/src/testcases/org/apache/poi/ss/formula/functions/TestSubtotal.java
new file mode 100644 (file)
index 0000000..54cf5b7
--- /dev/null
@@ -0,0 +1,72 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link Subtotal}
+ *
+ * @author Paul Tomlin
+ */
+public final class TestSubtotal extends TestCase {
+       private static final int FUNCTION_AVERAGE = 1;
+       private static final int FUNCTION_COUNT = 2;
+       private static final int FUNCTION_MAX = 4;
+       private static final int FUNCTION_MIN = 5;
+       private static final int FUNCTION_PRODUCT = 6;
+       private static final int FUNCTION_STDEV = 7;
+       private static final int FUNCTION_SUM = 9;
+
+       private static final double[] TEST_VALUES0 = {
+               1, 2,
+               3, 4,
+               5, 6,
+               7, 8,
+               9, 10
+       };
+
+       private static void confirmSubtotal(int function, double expected) {
+               ValueEval[] values = new ValueEval[TEST_VALUES0.length];
+               for (int i = 0; i < TEST_VALUES0.length; i++) {
+                       values[i] = new NumberEval(TEST_VALUES0[i]);
+               }
+
+               AreaEval arg1 = EvalFactory.createAreaEval("C1:D5", values);
+               ValueEval args[] = { new NumberEval(function), arg1 };
+
+               ValueEval result = new Subtotal().evaluate(args, 0, 0);
+
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(expected, ((NumberEval) result).getNumberValue(), 0.0);
+       }
+
+       public void testBasics() {
+               confirmSubtotal(FUNCTION_SUM, 55.0);
+               confirmSubtotal(FUNCTION_AVERAGE, 5.5);
+               confirmSubtotal(FUNCTION_COUNT, 10.0);
+               confirmSubtotal(FUNCTION_MAX, 10.0);
+               confirmSubtotal(FUNCTION_MIN, 1.0);
+               confirmSubtotal(FUNCTION_PRODUCT, 3628800.0);
+               confirmSubtotal(FUNCTION_STDEV, 3.0276503540974917);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java b/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java
new file mode 100644 (file)
index 0000000..1ef090e
--- /dev/null
@@ -0,0 +1,102 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.NumericValueEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Test cases for SUMPRODUCT()
+ *
+ * @author Josh Micich
+ */
+public final class TestSumif extends TestCase {
+       private static final NumberEval _30 = new NumberEval(30);
+       private static final NumberEval _40 = new NumberEval(40);
+       private static final NumberEval _50 = new NumberEval(50);
+       private static final NumberEval _60 = new NumberEval(60);
+
+       private static ValueEval invokeSumif(int rowIx, int colIx, ValueEval...args) {
+               return new Sumif().evaluate(args, rowIx, colIx);
+       }
+       private static void confirmDouble(double expected, ValueEval actualEval) {
+               if(!(actualEval instanceof NumericValueEval)) {
+                       throw new AssertionFailedError("Expected numeric result");
+               }
+               NumericValueEval nve = (NumericValueEval)actualEval;
+               assertEquals(expected, nve.getNumberValue(), 0);
+       }
+
+       public void testBasic() {
+               ValueEval[] arg0values = new ValueEval[] { _30, _30, _40, _40, _50, _50  };
+               ValueEval[] arg2values = new ValueEval[] { _30, _40, _50, _60, _60, _60 };
+
+               AreaEval arg0;
+               AreaEval arg2;
+
+               arg0 = EvalFactory.createAreaEval("A3:B5", arg0values);
+               arg2 = EvalFactory.createAreaEval("D1:E3", arg2values);
+
+               confirm(60.0, arg0, new NumberEval(30.0));
+               confirm(70.0, arg0, new NumberEval(30.0), arg2);
+               confirm(100.0, arg0, new StringEval(">45"));
+
+       }
+       private static void confirm(double expectedResult, ValueEval...args) {
+               confirmDouble(expectedResult, invokeSumif(-1, -1, args));
+       }
+
+
+       /**
+        * test for bug observed near svn r882931
+        */
+       public void testCriteriaArgRange() {
+               ValueEval[] arg0values = new ValueEval[] { _50, _60, _50, _50, _50, _30,  };
+               ValueEval[] arg1values = new ValueEval[] { _30, _40, _50, _60,  };
+
+               AreaEval arg0;
+               AreaEval arg1;
+               ValueEval ve;
+
+               arg0 = EvalFactory.createAreaEval("A3:B5", arg0values);
+               arg1 = EvalFactory.createAreaEval("A2:D2", arg1values); // single row range
+
+               ve = invokeSumif(0, 2, arg0, arg1);  // invoking from cell C1
+               if (ve instanceof NumberEval) {
+                       NumberEval ne = (NumberEval) ve;
+                       if (ne.getNumberValue() == 30.0) {
+                               throw new AssertionFailedError("identified error in SUMIF - criteria arg not evaluated properly");
+                       }
+               }
+
+               confirmDouble(200, ve);
+
+               arg0 = EvalFactory.createAreaEval("C1:D3", arg0values);
+               arg1 = EvalFactory.createAreaEval("B1:B4", arg1values); // single column range
+
+               ve = invokeSumif(3, 0, arg0, arg1); // invoking from cell A4
+
+               confirmDouble(60, ve);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestSumproduct.java b/src/testcases/org/apache/poi/ss/formula/functions/TestSumproduct.java
new file mode 100644 (file)
index 0000000..a8ccf47
--- /dev/null
@@ -0,0 +1,117 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.NumericValueEval;
+import org.apache.poi.ss.formula.eval.RefEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Test cases for SUMPRODUCT()
+ *
+ * @author Josh Micich
+ */
+public final class TestSumproduct extends TestCase {
+
+       private static ValueEval invokeSumproduct(ValueEval[] args) {
+               // srcCellRow and srcCellColumn are ignored by SUMPRODUCT
+               return new Sumproduct().evaluate(args, -1, (short)-1);
+       }
+       private static void confirmDouble(double expected, ValueEval actualEval) {
+               if(!(actualEval instanceof NumericValueEval)) {
+                       fail("Expected numeric result");
+               }
+               NumericValueEval nve = (NumericValueEval)actualEval;
+               assertEquals(expected, nve.getNumberValue(), 0);
+       }
+
+       public void testScalarSimple() {
+
+               RefEval refEval = EvalFactory.createRefEval("A1", new NumberEval(3));
+               ValueEval[] args = {
+                       refEval,
+                       new NumberEval(2),
+               };
+               ValueEval result = invokeSumproduct(args);
+               confirmDouble(6D, result);
+       }
+
+       public void testAreaSimple() {
+               ValueEval[] aValues = {
+                       new NumberEval(2),
+                       new NumberEval(4),
+                       new NumberEval(5),
+               };
+               ValueEval[] bValues = {
+                       new NumberEval(3),
+                       new NumberEval(6),
+                       new NumberEval(7),
+               };
+               AreaEval aeA = EvalFactory.createAreaEval("A1:A3", aValues);
+               AreaEval aeB = EvalFactory.createAreaEval("B1:B3", bValues);
+
+               ValueEval[] args = { aeA, aeB, };
+               ValueEval result = invokeSumproduct(args);
+               confirmDouble(65D, result);
+       }
+
+       /**
+        * For scalar products, the terms may be 1x1 area refs
+        */
+       public void testOneByOneArea() {
+
+               AreaEval ae = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(7), });
+
+               ValueEval[] args = {
+                               ae,
+                               new NumberEval(2),
+                       };
+               ValueEval result = invokeSumproduct(args);
+               confirmDouble(14D, result);
+       }
+
+       public void testMismatchAreaDimensions() {
+
+               AreaEval aeA = EvalFactory.createAreaEval("A1:A3", new ValueEval[3]);
+               AreaEval aeB = EvalFactory.createAreaEval("B1:D1", new ValueEval[3]);
+
+               ValueEval[] args;
+               args = new ValueEval[] { aeA, aeB, };
+               assertEquals(ErrorEval.VALUE_INVALID, invokeSumproduct(args));
+
+               args = new ValueEval[] { aeA, new NumberEval(5), };
+               assertEquals(ErrorEval.VALUE_INVALID, invokeSumproduct(args));
+       }
+
+       public void testAreaWithErrorCell() {
+               ValueEval[] aValues = {
+                       ErrorEval.REF_INVALID,
+                       null,
+               };
+               AreaEval aeA = EvalFactory.createAreaEval("A1:A2", aValues);
+               AreaEval aeB = EvalFactory.createAreaEval("B1:B2", new ValueEval[2]);
+
+               ValueEval[] args = { aeA, aeB, };
+               assertEquals(ErrorEval.REF_INVALID, invokeSumproduct(args));
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java b/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java
new file mode 100644 (file)
index 0000000..4e1209b
--- /dev/null
@@ -0,0 +1,132 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.AreaEval;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Test cases for Excel function T()
+ *
+ * @author Josh Micich
+ */
+public final class TestTFunc extends TestCase {
+
+       /**
+        * @return the result of calling function T() with the specified argument
+        */
+       private static ValueEval invokeT(ValueEval arg) {
+               ValueEval[] args = { arg, };
+               ValueEval result = new T().evaluate(args, -1, (short)-1);
+               assertNotNull("result may never be null", result);
+               return result;
+       }
+       /**
+        * Simulates call: T(A1)
+        * where cell A1 has the specified innerValue
+        */
+       private ValueEval invokeTWithReference(ValueEval innerValue) {
+               ValueEval arg = EvalFactory.createRefEval("$B$2", innerValue);
+               return invokeT(arg);
+       }
+
+       private static void confirmText(String text) {
+               ValueEval arg = new StringEval(text);
+               ValueEval eval = invokeT(arg);
+               StringEval se = (StringEval) eval;
+               assertEquals(text, se.getStringValue());
+       }
+
+       public void testTextValues() {
+
+               confirmText("abc");
+               confirmText("");
+               confirmText(" ");
+               confirmText("~");
+               confirmText("123");
+               confirmText("TRUE");
+       }
+
+       private static void confirmError(ValueEval arg) {
+               ValueEval eval = invokeT(arg);
+               assertTrue(arg == eval);
+       }
+
+       public void testErrorValues() {
+
+               confirmError(ErrorEval.VALUE_INVALID);
+               confirmError(ErrorEval.NA);
+               confirmError(ErrorEval.REF_INVALID);
+       }
+
+       private static void confirmString(ValueEval eval, String expected) {
+               assertTrue(eval instanceof StringEval);
+               assertEquals(expected, ((StringEval)eval).getStringValue());
+       }
+
+       private static void confirmOther(ValueEval arg) {
+               ValueEval eval = invokeT(arg);
+               confirmString(eval, "");
+       }
+
+       public void testOtherValues() {
+               confirmOther(new NumberEval(2));
+               confirmOther(BoolEval.FALSE);
+               confirmOther(BlankEval.instance);  // can this particular case be verified?
+       }
+
+       public void testRefValues() {
+               ValueEval eval;
+
+               eval = invokeTWithReference(new StringEval("def"));
+               confirmString(eval, "def");
+               eval = invokeTWithReference(new StringEval(" "));
+               confirmString(eval, " ");
+
+               eval = invokeTWithReference(new NumberEval(2));
+               confirmString(eval, "");
+               eval = invokeTWithReference(BoolEval.TRUE);
+               confirmString(eval, "");
+
+               eval = invokeTWithReference(ErrorEval.NAME_INVALID);
+               assertTrue(eval == ErrorEval.NAME_INVALID);
+       }
+
+       public void testAreaArg() {
+               ValueEval[] areaValues = new ValueEval[] {
+                       new StringEval("abc"), new StringEval("def"),
+                       new StringEval("ghi"), new StringEval("jkl"),
+               };
+               AreaEval ae = EvalFactory.createAreaEval("C10:D11", areaValues);
+
+               ValueEval ve;
+               ve = invokeT(ae);
+               confirmString(ve, "abc");
+
+               areaValues[0] = new NumberEval(5.0);
+               ve = invokeT(ae);
+               confirmString(ve, "");
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestText.java b/src/testcases/org/apache/poi/ss/formula/functions/TestText.java
new file mode 100644 (file)
index 0000000..8ff0bbf
--- /dev/null
@@ -0,0 +1,113 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.text.DecimalFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+
+/**
+ * Test case for TEXT()
+ *
+ * @author Stephen Wolke (smwolke at geistig.com)
+ */
+public final class TestText extends TestCase {
+       private static final TextFunction T = null;
+
+       public void testTextWithStringFirstArg() {
+
+               ValueEval strArg = new StringEval("abc");
+               ValueEval formatArg = new StringEval("abc");
+               ValueEval[] args = { strArg, formatArg };
+               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
+               assertEquals(ErrorEval.VALUE_INVALID, result);
+       }
+
+       public void testTextWithDeciamlFormatSecondArg() {
+
+               ValueEval numArg = new NumberEval(321321.321);
+               ValueEval formatArg = new StringEval("#,###.00000");
+               ValueEval[] args = { numArg, formatArg };
+               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
+               char groupSeparator = new DecimalFormatSymbols(Locale.getDefault()).getGroupingSeparator();
+               char decimalSeparator = new DecimalFormatSymbols(Locale.getDefault()).getDecimalSeparator();
+               ValueEval testResult = new StringEval("321" + groupSeparator + "321" + decimalSeparator + "32100");
+               assertEquals(testResult.toString(), result.toString());
+               numArg = new NumberEval(321.321);
+               formatArg = new StringEval("00000.00000");
+               args[0] = numArg;
+               args[1] = formatArg;
+               result = T.TEXT.evaluate(args, -1, (short)-1);
+               testResult = new StringEval("00321" + decimalSeparator + "32100");
+               assertEquals(testResult.toString(), result.toString());
+
+               formatArg = new StringEval("$#.#");
+               args[1] = formatArg;
+               result = T.TEXT.evaluate(args, -1, (short)-1);
+               testResult = new StringEval("$321" + decimalSeparator + "3");
+               assertEquals(testResult.toString(), result.toString());
+       }
+
+       public void testTextWithFractionFormatSecondArg() {
+
+               ValueEval numArg = new NumberEval(321.321);
+               ValueEval formatArg = new StringEval("# #/#");
+               ValueEval[] args = { numArg, formatArg };
+               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
+               ValueEval testResult = new StringEval("321 1/3");
+               assertEquals(testResult.toString(), result.toString());
+
+               formatArg = new StringEval("# #/##");
+               args[1] = formatArg;
+               result = T.TEXT.evaluate(args, -1, (short)-1);
+               testResult = new StringEval("321 26/81");
+               assertEquals(testResult.toString(), result.toString());
+
+               formatArg = new StringEval("#/##");
+               args[1] = formatArg;
+               result = T.TEXT.evaluate(args, -1, (short)-1);
+               testResult = new StringEval("26027/81");
+               assertEquals(testResult.toString(), result.toString());
+       }
+
+       public void testTextWithDateFormatSecondArg() {
+
+               ValueEval numArg = new NumberEval(321.321);
+               ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
+               ValueEval[] args = { numArg, formatArg };
+               ValueEval result = T.TEXT.evaluate(args, -1, (short)-1);
+               ValueEval testResult = new StringEval("16:11:1900 07:42:14");
+               assertEquals(testResult.toString(), result.toString());
+
+               // this line is intended to compute how "November" would look like in the current locale
+               String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime());
+
+               formatArg = new StringEval("MMMM dd, yyyy");
+               args[1] = formatArg;
+               result = T.TEXT.evaluate(args, -1, (short)-1);
+               testResult = new StringEval(november + " 16, 1900");
+               assertEquals(testResult.toString(), result.toString());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestTime.java b/src/testcases/org/apache/poi/ss/formula/functions/TestTime.java
new file mode 100644 (file)
index 0000000..a1f89ff
--- /dev/null
@@ -0,0 +1,122 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Tests for {@link TimeFunc}
+ *
+ * @author @author Steven Butler (sebutler @ gmail dot com)
+ */
+public final class TestTime extends TestCase {
+
+       private static final int SECONDS_PER_MINUTE = 60;
+       private static final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
+       private static final double SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;
+       private HSSFCell cell11;
+       private HSSFFormulaEvaluator evaluator;
+       private HSSFWorkbook wb;
+       private HSSFDataFormatter form;
+       private HSSFCellStyle style;
+
+       public void setUp() {
+               wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet("new sheet");
+               style = wb.createCellStyle();
+               HSSFDataFormat fmt = wb.createDataFormat();
+               style.setDataFormat(fmt.getFormat("hh:mm:ss"));
+
+               cell11 = sheet.createRow(0).createCell(0);
+               form = new HSSFDataFormatter();
+
+               evaluator = new HSSFFormulaEvaluator(wb);
+       }
+
+       public void testSomeArgumentsMissing() {
+               confirm("00:00:00", "TIME(, 0, 0)");
+               confirm("12:00:00", "TIME(12, , )");
+       }
+
+       public void testValid() {
+               confirm("00:00:01", 0, 0, 1);
+               confirm("00:01:00", 0, 1, 0);
+
+               confirm("00:00:00", 0, 0, 0);
+
+               confirm("01:00:00", 1, 0, 0);
+               confirm("12:00:00", 12, 0, 0);
+               confirm("23:00:00", 23, 0, 0);
+               confirm("00:00:00", 24, 0, 0);
+               confirm("01:00:00", 25, 0, 0);
+               confirm("00:00:00", 48, 0, 0);
+               confirm("06:00:00", 6, 0, 0);
+               confirm("06:01:00", 6, 1, 0);
+               confirm("06:30:00", 6, 30, 0);
+
+               confirm("06:59:00", 6, 59, 0);
+               confirm("07:00:00", 6, 60, 0);
+               confirm("07:01:00", 6, 61, 0);
+               confirm("08:00:00", 6, 120, 0);
+               confirm("06:00:00", 6, 1440, 0);
+               confirm("18:49:00", 18, 49, 0);
+               confirm("18:49:01", 18, 49, 1);
+               confirm("18:49:30", 18, 49, 30);
+               confirm("18:49:59", 18, 49, 59);
+               confirm("18:50:00", 18, 49, 60);
+               confirm("18:50:01", 18, 49, 61);
+               confirm("18:50:59", 18, 49, 119);
+               confirm("18:51:00", 18, 49, 120);
+               confirm("03:55:07", 18, 49, 32767);
+               confirm("12:08:01", 18, 32767, 61);
+               confirm("07:50:01", 32767, 49, 61);
+       }
+       private void confirm(String expectedTimeStr, int inH, int inM, int inS) {
+               confirm(expectedTimeStr, "TIME(" + inH + "," + inM + "," + inS + ")");
+       }
+
+       private void confirm(String expectedTimeStr, String formulaText) {
+//             System.out.println("=" + formulaText);
+               String[] parts = Pattern.compile(":").split(expectedTimeStr);
+               int expH = Integer.parseInt(parts[0]);
+               int expM = Integer.parseInt(parts[1]);
+               int expS = Integer.parseInt(parts[2]);
+
+               double expectedValue = (expH*SECONDS_PER_HOUR + expM*SECONDS_PER_MINUTE + expS)/SECONDS_PER_DAY;
+
+               cell11.setCellFormula(formulaText);
+               cell11.setCellStyle(style);
+               evaluator.clearAllCachedResultValues();
+
+               double actualValue = evaluator.evaluate(cell11).getNumberValue();
+               assertEquals(expectedValue, actualValue, 0.0);
+
+               String actualText = form.formatCellValue(cell11, evaluator);
+               assertEquals(expectedTimeStr, actualText);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestTrim.java b/src/testcases/org/apache/poi/ss/formula/functions/TestTrim.java
new file mode 100644 (file)
index 0000000..bb5efa7
--- /dev/null
@@ -0,0 +1,78 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+/**
+ * Tests for Excel function TRIM()
+ *
+ * @author Josh Micich
+ */
+public final class TestTrim extends TestCase {
+
+
+       private static ValueEval invokeTrim(ValueEval text) {
+               ValueEval[] args = new ValueEval[] { text, };
+               return TextFunction.TRIM.evaluate(args, -1, (short)-1);
+       }
+
+       private void confirmTrim(ValueEval text, String expected) {
+               ValueEval result = invokeTrim(text);
+               assertEquals(StringEval.class, result.getClass());
+               assertEquals(expected, ((StringEval)result).getStringValue());
+       }
+
+       private void confirmTrim(ValueEval text, ErrorEval expectedError) {
+               ValueEval result = invokeTrim(text);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
+       }
+
+       public void testBasic() {
+
+               confirmTrim(new StringEval(" hi "), "hi");
+               confirmTrim(new StringEval("hi "), "hi");
+               confirmTrim(new StringEval("  hi"), "hi");
+               confirmTrim(new StringEval(" hi there  "), "hi there");
+               confirmTrim(new StringEval(""), "");
+               confirmTrim(new StringEval("   "), "");
+       }
+
+       /**
+        * Valid cases where text arg is not exactly a string
+        */
+       public void testUnusualArgs() {
+
+               // text (first) arg type is number, other args are strings with fractional digits
+               confirmTrim(new NumberEval(123456), "123456");
+               confirmTrim(BoolEval.FALSE, "FALSE");
+               confirmTrim(BoolEval.TRUE, "TRUE");
+               confirmTrim(BlankEval.instance, "");
+       }
+
+       public void testErrors() {
+               confirmTrim(ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestTrunc.java b/src/testcases/org/apache/poi/ss/formula/functions/TestTrunc.java
new file mode 100644 (file)
index 0000000..c3ed459
--- /dev/null
@@ -0,0 +1,59 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+
+/**
+ * Test case for TRUNC()
+ *
+ * @author Stephen Wolke (smwolke at geistig.com)
+ */
+public final class TestTrunc extends AbstractNumericTestCase {
+       private static final NumericFunction F = null;
+       public void testTruncWithStringArg() {
+
+               ValueEval strArg = new StringEval("abc");
+               ValueEval[] args = { strArg, new NumberEval(2) };
+               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
+               assertEquals(ErrorEval.VALUE_INVALID, result);
+       }
+
+       public void testTruncWithWholeNumber() {
+               ValueEval[] args = { new NumberEval(200), new NumberEval(2) };
+               @SuppressWarnings("static-access")
+               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
+               assertEquals("TRUNC", (new NumberEval(200d)).getNumberValue(), ((NumberEval)result).getNumberValue());
+       }
+       
+       public void testTruncWithDecimalNumber() {
+               ValueEval[] args = { new NumberEval(2.612777), new NumberEval(3) };
+               @SuppressWarnings("static-access")
+               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
+               assertEquals("TRUNC", (new NumberEval(2.612d)).getNumberValue(), ((NumberEval)result).getNumberValue());
+       }
+       
+       public void testTruncWithDecimalNumberOneArg() {
+               ValueEval[] args = { new NumberEval(2.612777) };
+               ValueEval result = F.TRUNC.evaluate(args, -1, (short)-1);
+               assertEquals("TRUNC", (new NumberEval(2d)).getNumberValue(), ((NumberEval)result).getNumberValue());
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestValue.java b/src/testcases/org/apache/poi/ss/formula/functions/TestValue.java
new file mode 100644 (file)
index 0000000..f85db0c
--- /dev/null
@@ -0,0 +1,94 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+
+/**
+ * Tests for {@link Value}
+ *
+ * @author Josh Micich
+ */
+public final class TestValue extends TestCase {
+
+       private static ValueEval invokeValue(String strText) {
+               ValueEval[] args = new ValueEval[] { new StringEval(strText), };
+               return new Value().evaluate(args, -1, (short) -1);
+       }
+
+       private static void confirmValue(String strText, double expected) {
+               ValueEval result = invokeValue(strText);
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(expected, ((NumberEval) result).getNumberValue(), 0.0);
+       }
+
+       private static void confirmValueError(String strText) {
+               ValueEval result = invokeValue(strText);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(ErrorEval.VALUE_INVALID, result);
+       }
+
+       public void testBasic() {
+
+               confirmValue("100", 100);
+               confirmValue("-2.3", -2.3);
+               confirmValue(".5", 0.5);
+               confirmValue(".5e2", 50);
+               confirmValue(".5e-2", 0.005);
+               confirmValue(".5e+2", 50);
+               confirmValue("+5", 5);
+               confirmValue("$1,000", 1000);
+               confirmValue("100.5e1", 1005);
+               confirmValue("1,0000", 10000);
+               confirmValue("1,000,0000", 10000000);
+               confirmValue("1,000,0000,00000", 1000000000000.0);
+               confirmValue(" 100 ", 100);
+               confirmValue(" + 100", 100);
+               confirmValue("10000", 10000);
+               confirmValue("$-5", -5);
+               confirmValue("$.5", 0.5);
+               confirmValue("123e+5", 12300000);
+               confirmValue("1,000e2", 100000);
+               confirmValue("$10e2", 1000);
+               confirmValue("$1,000e2", 100000);
+       }
+
+       public void testErrors() {
+               confirmValueError("1+1");
+               confirmValueError("1 1");
+               confirmValueError("1,00.0");
+               confirmValueError("1,00");
+               confirmValueError("$1,00.5e1");
+               confirmValueError("1,00.5e1");
+               confirmValueError("1,0,000");
+               confirmValueError("1,00,000");
+               confirmValueError("++100");
+               confirmValueError("$$5");
+               confirmValueError("-");
+               confirmValueError("+");
+               confirmValueError("$");
+               confirmValueError(",300");
+               confirmValueError("0.233,4");
+               confirmValueError("1e2.5");
+       }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestXYNumericFunction.java b/src/testcases/org/apache/poi/ss/formula/functions/TestXYNumericFunction.java
new file mode 100644 (file)
index 0000000..cc7f91a
--- /dev/null
@@ -0,0 +1,135 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.poi.ss.formula.functions;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+/**
+ * Tests for Excel functions SUMX2MY2(), SUMX2PY2(), SUMXMY2()
+ *
+ * @author Josh Micich
+ */
+public final class TestXYNumericFunction extends TestCase {
+       private static final Function SUM_SQUARES = new Sumx2py2();
+       private static final Function DIFF_SQUARES = new Sumx2my2();
+       private static final Function SUM_SQUARES_OF_DIFFS = new Sumxmy2();
+
+       private static ValueEval invoke(Function function, ValueEval xArray, ValueEval yArray) {
+               ValueEval[] args = new ValueEval[] { xArray, yArray, };
+               return function.evaluate(args, -1, (short)-1);
+       }
+
+       private void confirm(Function function, ValueEval xArray, ValueEval yArray, double expected) {
+               ValueEval result = invoke(function, xArray, yArray);
+               assertEquals(NumberEval.class, result.getClass());
+               assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
+       }
+       private void confirmError(Function function, ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
+               ValueEval result = invoke(function, xArray, yArray);
+               assertEquals(ErrorEval.class, result.getClass());
+               assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
+       }
+
+       private void confirmError(ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
+               confirmError(SUM_SQUARES, xArray, yArray, expectedError);
+               confirmError(DIFF_SQUARES, xArray, yArray, expectedError);
+               confirmError(SUM_SQUARES_OF_DIFFS, xArray, yArray, expectedError);
+       }
+
+       public void testBasic() {
+               ValueEval[] xValues = {
+                       new NumberEval(1),
+                       new NumberEval(2),
+               };
+               ValueEval areaEvalX = createAreaEval(xValues);
+               confirm(SUM_SQUARES, areaEvalX, areaEvalX, 10.0);
+               confirm(DIFF_SQUARES, areaEvalX, areaEvalX, 0.0);
+               confirm(SUM_SQUARES_OF_DIFFS, areaEvalX, areaEvalX, 0.0);
+
+               ValueEval[] yValues = {
+                       new NumberEval(3),
+                       new NumberEval(4),
+               };
+               ValueEval areaEvalY = createAreaEval(yValues);
+               confirm(SUM_SQUARES, areaEvalX, areaEvalY, 30.0);
+               confirm(DIFF_SQUARES, areaEvalX, areaEvalY, -20.0);
+               confirm(SUM_SQUARES_OF_DIFFS, areaEvalX, areaEvalY, 8.0);
+       }
+
+       /**
+        * number of items in array is not limited to 30
+        */
+       public void testLargeArrays() {
+               ValueEval[] xValues = createMockNumberArray(100, 3);
+               ValueEval[] yValues = createMockNumberArray(100, 2);
+
+               confirm(SUM_SQUARES, createAreaEval(xValues), createAreaEval(yValues), 1300.0);
+               confirm(DIFF_SQUARES, createAreaEval(xValues), createAreaEval(yValues), 500.0);
+               confirm(SUM_SQUARES_OF_DIFFS, createAreaEval(xValues), createAreaEval(yValues), 100.0);
+       }
+
+
+       private ValueEval[] createMockNumberArray(int size, double value) {
+               ValueEval[] result = new ValueEval[size];
+               for (int i = 0; i < result.length; i++) {
+                       result[i] = new NumberEval(value);
+               }
+               return result;
+       }
+
+       private static ValueEval createAreaEval(ValueEval[] values) {
+               String refStr = "A1:A" + values.length;
+               return EvalFactory.createAreaEval(refStr, values);
+       }
+
+       public void testErrors() {
+               ValueEval[] xValues = {
+                               ErrorEval.REF_INVALID,
+                               new NumberEval(2),
+               };
+               ValueEval areaEvalX = createAreaEval(xValues);
+               ValueEval[] yValues = {
+                               new NumberEval(2),
+                               ErrorEval.NULL_INTERSECTION,
+               };
+               ValueEval areaEvalY = createAreaEval(yValues);
+               ValueEval[] zValues = { // wrong size
+                               new NumberEval(2),
+               };
+               ValueEval areaEvalZ = createAreaEval(zValues);
+
+               // if either arg is an error, that error propagates
+               confirmError(ErrorEval.REF_INVALID, ErrorEval.NAME_INVALID, ErrorEval.REF_INVALID);
+               confirmError(areaEvalX, ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
+               confirmError(ErrorEval.NAME_INVALID, areaEvalX, ErrorEval.NAME_INVALID);
+
+               // array sizes must match
+               confirmError(areaEvalX, areaEvalZ, ErrorEval.NA);
+               confirmError(areaEvalZ, areaEvalY, ErrorEval.NA);
+
+               // any error in an array item propagates up
+               confirmError(areaEvalX, areaEvalX, ErrorEval.REF_INVALID);
+
+               // search for errors array by array, not pair by pair
+               confirmError(areaEvalX, areaEvalY, ErrorEval.REF_INVALID);
+               confirmError(areaEvalY, areaEvalX, ErrorEval.NULL_INTERSECTION);
+       }
+}
index 833e5aab9a6efd74d86dd6ef3d89116dfacc5c02..e0be21b0fd4f1c93fc1609fc20d67e93f5a8be46 100644 (file)
@@ -19,7 +19,6 @@ package org.apache.poi.ss.usermodel;
 
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.ss.ITestDataProvider;
 
 /**
index d2518effb1a136357061760c0e5e63295192ed2d..f9346a67af18f4500dfbf8a74a9284daa5c5d9ca 100644 (file)
@@ -20,7 +20,6 @@ package org.apache.poi.ss.usermodel;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.usermodel.HSSFName;
 import org.apache.poi.ss.ITestDataProvider;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
@@ -506,7 +505,7 @@ public abstract class BaseTestNamedRange extends TestCase {
      * 00000010 | 00 00 00 55 50 53 53 74 61 74 65                | ...UPSState
      * </pre>
      *
-     * This caused trouble for anything that requires {@link HSSFName#getRefersToFormula()}
+     * This caused trouble for anything that requires {@link Name#getRefersToFormula()}
      * It is easy enough to re-create the the same data (by not setting the formula). Excel
      * seems to gracefully remove this uninitialized name record.  It would be nice if POI
      * could do the same, but that would involve adjusting subsequent name indexes across