]> source.dussan.org Git - poi.git/commitdiff
Minor improvements to error handling in ForkedEvaluator. Added junits.
authorJosh Micich <josh@apache.org>
Wed, 30 Sep 2009 22:25:53 +0000 (22:25 +0000)
committerJosh Micich <josh@apache.org>
Wed, 30 Sep 2009 22:25:53 +0000 (22:25 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@820479 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationSheet.java
src/testcases/org/apache/poi/ss/formula/AllSSFormulaTests.java
src/testcases/org/apache/poi/ss/formula/eval/forked/TestForkedEvaluator.java [new file with mode: 0644]

index c36232a1d8585038da610027d3a169f8190bfad2..196bfa69ddfb68d18628204692182535d2899cd4 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.poi.ss.formula.EvaluationWorkbook;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellReference;
 
 /**
  * Represents a sheet being used for forked evaluation.  Initially, objects of this class contain
@@ -65,6 +66,11 @@ final class ForkedEvaluationSheet implements EvaluationSheet {
                ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
                if (result == null) {
                        EvaluationCell mcell = _masterSheet.getCell(rowIndex, columnIndex);
+                       if (mcell == null) {
+                               CellReference cr = new CellReference(rowIndex, columnIndex);
+                               throw new UnsupportedOperationException("Underlying cell '"
+                                               + cr.formatAsString() + "' is missing in master sheet.");
+                       }
                        result = new ForkedEvaluationCell(this, mcell);
                        _sharedCellsByRowCol.put(key, result);
                }
index 13e2cfecdf48ce8662f4de89501ea5634d22235d..970d0f373adb5ded35f5bd0e5222b52ee3adaf0d 100644 (file)
 
 package org.apache.poi.ss.formula;
 
+import org.apache.poi.ss.formula.eval.forked.TestForkedEvaluator;
+
 import junit.framework.Test;
 import junit.framework.TestSuite;
 /**
  * Test suite for org.apache.poi.ss.formula
- * 
+ *
  * @author Josh Micich
  */
 public final class AllSSFormulaTests {
-    public static Test suite() {
+       public static Test suite() {
                TestSuite result = new TestSuite(AllSSFormulaTests.class.getName());
                result.addTestSuite(TestCellCacheEntry.class);
                result.addTestSuite(TestEvaluationCache.class);
                result.addTestSuite(TestWorkbookEvaluator.class);
+               result.addTestSuite(TestForkedEvaluator.class);
                return result;
        }
 }
diff --git a/src/testcases/org/apache/poi/ss/formula/eval/forked/TestForkedEvaluator.java b/src/testcases/org/apache/poi/ss/formula/eval/forked/TestForkedEvaluator.java
new file mode 100644 (file)
index 0000000..1e48069
--- /dev/null
@@ -0,0 +1,118 @@
+/* ====================================================================
+   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.forked;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+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.IStabilityClassifier;
+
+/**
+ * @author Josh Micich
+ */
+public final class TestForkedEvaluator extends TestCase {
+       /**
+        * set up a calculation workbook with input cells nicely segregated on a
+        * sheet called "Inputs"
+        */
+       private static HSSFWorkbook createWorkbook() {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet1 = wb.createSheet("Inputs");
+               HSSFSheet sheet2 = wb.createSheet("Calculations");
+               HSSFRow row;
+               row = sheet2.createRow(0);
+               row.createCell(0).setCellFormula("B1*Inputs!A1-Inputs!B1");
+               row.createCell(1).setCellValue(5.0); // Calculations!B1
+
+               // some default input values
+               row = sheet1.createRow(0);
+               row.createCell(0).setCellValue(2.0); // Inputs!A1
+               row.createCell(1).setCellValue(3.0); // Inputs!B1
+               return wb;
+       }
+
+       /**
+        * Shows a basic use-case for {@link ForkedEvaluator}
+        */
+       public void testBasic() {
+               HSSFWorkbook wb = createWorkbook();
+
+               // The stability classifier is useful to reduce memory consumption of caching logic
+               IStabilityClassifier stabilityClassifier = new IStabilityClassifier() {
+                       public boolean isCellFinal(int sheetIndex, int rowIndex, int columnIndex) {
+                               return sheetIndex == 1;
+                       }
+               };
+
+               ForkedEvaluator fe1 = ForkedEvaluator.create(wb, stabilityClassifier, null);
+               ForkedEvaluator fe2 = ForkedEvaluator.create(wb, stabilityClassifier, null);
+
+               // fe1 and fe2 can be used concurrently on separate threads
+
+               fe1.updateCell("Inputs", 0, 0, new NumberEval(4.0));
+               fe1.updateCell("Inputs", 0, 1, new NumberEval(1.1));
+
+               fe2.updateCell("Inputs", 0, 0, new NumberEval(1.2));
+               fe2.updateCell("Inputs", 0, 1, new NumberEval(2.0));
+
+               assertEquals(18.9, ((NumberEval) fe1.evaluate("Calculations", 0, 0)).getNumberValue(), 0.0);
+               assertEquals(4.0, ((NumberEval) fe2.evaluate("Calculations", 0, 0)).getNumberValue(), 0.0);
+               fe1.updateCell("Inputs", 0, 0, new NumberEval(3.0));
+               assertEquals(13.9, ((NumberEval) fe1.evaluate("Calculations", 0, 0)).getNumberValue(), 0.0);
+       }
+
+       /**
+        * As of Sep 2009, the Forked evaluator can update values from existing cells (this is because
+        * the underlying 'master' cell is used as a key into the calculation cache.  Prior to the fix
+        * for this bug, an attempt to update a missing cell would result in NPE.  This junit tests for
+        * a more meaningful error message.<br/>
+        *
+        * An alternate solution might involve allowing empty cells to be created as necessary.  That
+        * was considered less desirable because so far, the underlying 'master' workbook is strictly
+        * <i>read-only</i> with respect to the ForkedEvaluator.
+        */
+       public void testMissingInputCell() {
+               HSSFWorkbook wb = createWorkbook();
+
+               ForkedEvaluator fe = ForkedEvaluator.create(wb, null, null);
+
+               // attempt update input at cell A2 (which is missing)
+               try {
+                       fe.updateCell("Inputs", 1, 0, new NumberEval(4.0));
+                       throw new AssertionFailedError(
+                                       "Expected exception to be thrown due to missing input cell");
+               } catch (NullPointerException e) {
+                       StackTraceElement[] stes = e.getStackTrace();
+                       if (stes[0].getMethodName().equals("getIdentityKey")) {
+                               throw new AssertionFailedError("Identified bug with update of missing input cell");
+                       }
+                       throw e;
+               } catch (UnsupportedOperationException e) {
+                       if (e.getMessage().equals(
+                                       "Underlying cell 'A2' is missing in master sheet.")) {
+                               // expected during successful test
+                       } else {
+                               throw e;
+                       }
+               }
+       }
+}