poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ye...@apache.org
Subject svn commit: r1142181 - in /poi/trunk/src: documentation/content/xdocs/status.xml java/org/apache/poi/ss/formula/PlainCellCache.java testcases/org/apache/poi/ss/formula/TestEvaluationCache.java testcases/org/apache/poi/ss/formula/TestPlainCellCache.java
Date Sat, 02 Jul 2011 09:05:36 GMT
Author: yegor
Date: Sat Jul  2 09:05:35 2011
New Revision: 1142181

URL: http://svn.apache.org/viewvc?rev=1142181&view=rev
Log:
Bug 51448 - Avoid exception when evaluating workbooks with more than 256 sheets

Added:
    poi/trunk/src/testcases/org/apache/poi/ss/formula/TestPlainCellCache.java
      - copied, changed from r1141898, poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java
Modified:
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/ss/formula/PlainCellCache.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=1142181&r1=1142180&r2=1142181&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Sat Jul  2 09:05:35 2011
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
+           <action dev="poi-developers" type="fix">51448 - Avoid exception when evaluating
workbooks with more than 256 sheets </action>
            <action dev="poi-developers" type="fix">51458 - Correct BitField wrapping
when setting large values</action>
            <action dev="poi-developers" type="add">51460 - Improve HSSF performance
when loading very long rows, by switching the CellValue array to an iterator</action>
            <action dev="poi-developers" type="fix">51444 - Prevent corrupted output
when saving files created by LibreOffice 3.3 </action>

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/PlainCellCache.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/PlainCellCache.java?rev=1142181&r1=1142180&r2=1142181&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/PlainCellCache.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/PlainCellCache.java Sat Jul  2 09:05:35 2011
@@ -28,7 +28,7 @@ final class PlainCellCache {
 
 	public static final class Loc {
 
-		private final int _bookSheetColumn;
+		private final long _bookSheetColumn;
 
 		private final int _rowIndex;
 
@@ -37,18 +37,19 @@ final class PlainCellCache {
 			_rowIndex = rowIndex;
 		}
 
-		public static int toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
-			return ((bookIndex & 0x00FF) << 24) + ((sheetIndex & 0x00FF) << 16)
-					+ ((columnIndex & 0xFFFF) << 0);
+		public static long toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
+			return ((bookIndex   & 0xFFFFl) << 48)  +
+                   ((sheetIndex  & 0xFFFFl) << 32) +
+                   ((columnIndex & 0xFFFFl) << 0);
 		}
 
-		public Loc(int bookSheetColumn, int rowIndex) {
+		public Loc(long bookSheetColumn, int rowIndex) {
 			_bookSheetColumn = bookSheetColumn;
 			_rowIndex = rowIndex;
 		}
 
 		public int hashCode() {
-			return _bookSheetColumn + 17 * _rowIndex;
+			return (int)(_bookSheetColumn ^ (_bookSheetColumn >>> 32)) + 17 * _rowIndex;
 		}
 
 		public boolean equals(Object obj) {
@@ -60,9 +61,18 @@ final class PlainCellCache {
 		public int getRowIndex() {
 			return _rowIndex;
 		}
+
 		public int getColumnIndex() {
-			return _bookSheetColumn & 0x000FFFF;
+            return (int)(_bookSheetColumn & 0x000FFFF);
 		}
+
+        public int getSheetIndex() {
+            return (int)((_bookSheetColumn >> 32) & 0xFFFF);
+        }
+
+        public int getBookIndex() {
+            return (int)((_bookSheetColumn >> 48) & 0xFFFF);
+        }
 	}
 
 	private Map<Loc, PlainValueCellCacheEntry> _plainValueEntriesByLoc;

Modified: poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java?rev=1142181&r1=1142180&r2=1142181&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java Sat Jul  2
09:05:35 2011
@@ -46,7 +46,7 @@ import org.apache.poi.hssf.usermodel.HSS
 import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
 import org.apache.poi.ss.formula.PlainCellCache.Loc;
-import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.*;
 
 /**
  * Tests {@link org.apache.poi.ss.formula.EvaluationCache}.  Makes sure that where possible
(previously calculated) cached
@@ -696,4 +696,82 @@ public class TestEvaluationCache extends
 			ps.println('"' + log[i] + "\",");
 		}
 	}
+
+    private static void testPlainValueCache(Workbook wb, int numberOfSheets) {
+
+        Row row;
+        Cell cell;
+
+        //create summary sheet
+        Sheet summary = wb.createSheet("summary");
+        wb.setActiveSheet(wb.getSheetIndex(summary));
+
+        //formula referring all sheets created below
+        row = summary.createRow(0);
+        Cell summaryCell = row.createCell(0);
+        summaryCell.setCellFormula("SUM(A2:A" + (numberOfSheets + 2) + ")");
+
+
+        //create sheets with cells having (different) numbers
+        // and add a row to summary
+        for (int i = 1; i < numberOfSheets; i++) {
+            Sheet sheet = wb.createSheet("new" + i);
+
+            row = sheet.createRow(0);
+            cell = row.createCell(0);
+            cell.setCellValue(i);
+
+            row = summary.createRow(i);
+            cell = row.createCell(0);
+            cell.setCellFormula("new" + i + "!A1");
+
+        }
+
+
+        //calculate
+        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
+        evaluator.evaluateFormulaCell(summaryCell);
+    }
+
+
+    public void testPlainValueCache()  {
+
+        Workbook wb = new HSSFWorkbook();
+        int numberOfSheets = 4098; // Bug 51448 reported that  Evaluation Cache got messed
up after 256 sheets
+
+        Row row;
+        Cell cell;
+
+        //create summary sheet
+        Sheet summary = wb.createSheet("summary");
+        wb.setActiveSheet(wb.getSheetIndex(summary));
+
+        //formula referring all sheets created below
+        row = summary.createRow(0);
+        Cell summaryCell = row.createCell(0);
+        summaryCell.setCellFormula("SUM(A2:A" + (numberOfSheets + 2) + ")");
+
+
+        //create sheets with cells having (different) numbers
+        // and add a row to summary
+        for (int i = 1; i < numberOfSheets; i++) {
+            Sheet sheet = wb.createSheet("new" + i);
+
+            row = sheet.createRow(0);
+            cell = row.createCell(0);
+            cell.setCellValue(i);
+
+            row = summary.createRow(i);
+            cell = row.createCell(0);
+            cell.setCellFormula("new" + i + "!A1");
+
+        }
+
+
+        //calculate
+        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
+        evaluator.evaluateFormulaCell(summaryCell);
+        assertEquals(8394753.0, summaryCell.getNumericCellValue());
+    }
+
 }

Copied: poi/trunk/src/testcases/org/apache/poi/ss/formula/TestPlainCellCache.java (from r1141898,
poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java)
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/TestPlainCellCache.java?p2=poi/trunk/src/testcases/org/apache/poi/ss/formula/TestPlainCellCache.java&p1=poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java&r1=1141898&r2=1142181&rev=1142181&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/TestPlainCellCache.java Sat Jul  2 09:05:35
2011
@@ -1,699 +1,75 @@
-/* ====================================================================
-   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.
-==================================================================== */
+/*
+ *  ====================================================================
+ *    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 java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
-
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.ss.formula.ptg.Ptg;
-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;
-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.usermodel.*;
 import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
 import org.apache.poi.ss.formula.PlainCellCache.Loc;
+import org.apache.poi.ss.formula.eval.*;
+import org.apache.poi.ss.formula.ptg.Ptg;
 import org.apache.poi.ss.usermodel.CellValue;
 
+import java.io.PrintStream;
+import java.util.*;
+
 /**
- * Tests {@link org.apache.poi.ss.formula.EvaluationCache}.  Makes sure that where possible
(previously calculated) cached
- * values are used.  Also checks that changing cell values causes the correct (minimal) set
of
- * dependent cached values to be cleared.
- *
- * @author Josh Micich
+ * @author Yegor Kozlov
  */
-public class TestEvaluationCache extends TestCase {
-
-	private static final class FormulaCellCacheEntryComparer implements Comparator<ICacheEntry>
{
-
-		private final Map<ICacheEntry,EvaluationCell> _formulaCellsByCacheEntry;
-
-		public FormulaCellCacheEntryComparer(Map<ICacheEntry,EvaluationCell> formulaCellsByCacheEntry)
{
-			_formulaCellsByCacheEntry = formulaCellsByCacheEntry;
-		}
-		private EvaluationCell getCell(ICacheEntry a) {
-			return _formulaCellsByCacheEntry.get(a);
-		}
-		public int compare(ICacheEntry oa, ICacheEntry ob) {
-			EvaluationCell a = getCell(oa);
-			EvaluationCell b = getCell(ob);
-			int cmp;
-			cmp = a.getRowIndex() - b.getRowIndex();
-			if (cmp != 0) {
-				return cmp;
-			}
-			cmp = a.getColumnIndex() - b.getColumnIndex();
-			if (cmp != 0) {
-				return cmp;
-			}
-			if (a.getSheet() == b.getSheet()) {
-				return 0;
-			}
-			throw new RuntimeException("Incomplete code - don't know how to order sheets");
-		}
-	}
-
-	private static final class EvalListener extends EvaluationListener {
-
-		private final List<String> _logList;
-		private final HSSFWorkbook _book;
-		private Map<ICacheEntry,EvaluationCell> _formulaCellsByCacheEntry;
-		private Map<ICacheEntry,Loc> _plainCellLocsByCacheEntry;
-
-		public EvalListener(HSSFWorkbook wb) {
-			_book = wb;
-			_logList = new ArrayList<String>();
-			_formulaCellsByCacheEntry = new HashMap<ICacheEntry,EvaluationCell>();
-			_plainCellLocsByCacheEntry = new HashMap<ICacheEntry, Loc>();
-		}
-		public void onCacheHit(int sheetIndex, int rowIndex, int columnIndex, ValueEval result)
{
-			log("hit", rowIndex, columnIndex, result);
-		}
-		public void onReadPlainValue(int sheetIndex, int rowIndex, int columnIndex, ICacheEntry
entry) {
-			Loc loc = new Loc(0, sheetIndex, rowIndex, columnIndex);
-			_plainCellLocsByCacheEntry.put(entry, loc);
-			log("value", rowIndex, columnIndex, entry.getValue());
-		}
-		public void onStartEvaluate(EvaluationCell cell, ICacheEntry entry) {
-			_formulaCellsByCacheEntry.put(entry, cell);
-			HSSFCell hc = _book.getSheetAt(0).getRow(cell.getRowIndex()).getCell(cell.getColumnIndex());
-			log("start", cell.getRowIndex(), cell.getColumnIndex(), FormulaExtractor.getPtgs(hc));
-		}
-		public void onEndEvaluate(ICacheEntry entry, ValueEval result) {
-			EvaluationCell cell = _formulaCellsByCacheEntry.get(entry);
-			log("end", cell.getRowIndex(), cell.getColumnIndex(), result);
-		}
-		public void onClearCachedValue(ICacheEntry entry) {
-			int rowIndex;
-			int columnIndex;
-			EvaluationCell cell = _formulaCellsByCacheEntry.get(entry);
-			if (cell == null) {
-				Loc loc = _plainCellLocsByCacheEntry.get(entry);
-				if (loc == null) {
-					throw new IllegalStateException("can't find cell or location");
-				}
-				rowIndex = loc.getRowIndex();
-				columnIndex = loc.getColumnIndex();
-			} else {
-				rowIndex = cell.getRowIndex();
-				columnIndex = cell.getColumnIndex();
-			}
-			log("clear", rowIndex, columnIndex, entry.getValue());
-		}
-		public void sortDependentCachedValues(ICacheEntry[] entries) {
-			Arrays.sort(entries, new FormulaCellCacheEntryComparer(_formulaCellsByCacheEntry));
-		}
-		public void onClearDependentCachedValue(ICacheEntry entry, int depth) {
-			EvaluationCell cell = _formulaCellsByCacheEntry.get(entry);
-			log("clear" + depth, cell.getRowIndex(), cell.getColumnIndex(), entry.getValue());
-		}
-
-		public void onChangeFromBlankValue(int sheetIndex, int rowIndex, int columnIndex,
-				EvaluationCell cell, ICacheEntry entry) {
-			log("changeFromBlank", rowIndex, columnIndex, entry.getValue());
-			if (entry.getValue() == null) { // hack to tell the difference between formula and plain
value
-				// perhaps the API could be improved: onChangeFromBlankToValue, onChangeFromBlankToFormula
-				_formulaCellsByCacheEntry.put(entry, cell);
-			} else {
-				Loc loc = new Loc(0, sheetIndex, rowIndex, columnIndex);
-				_plainCellLocsByCacheEntry.put(entry, loc);
-			}
-		}
-		private void log(String tag, int rowIndex, int columnIndex, Object value) {
-			StringBuffer sb = new StringBuffer(64);
-			sb.append(tag).append(' ');
-			sb.append(new CellReference(rowIndex, columnIndex, false, false).formatAsString());
-			if (value != null) {
-				sb.append(' ').append(formatValue(value));
-			}
-			_logList.add(sb.toString());
-		}
-		private String formatValue(Object value) {
-			if (value instanceof Ptg[]) {
-				Ptg[] ptgs = (Ptg[]) value;
-				return HSSFFormulaParser.toFormulaString(_book, ptgs);
-			}
-			if (value instanceof NumberEval) {
-				NumberEval ne = (NumberEval) value;
-				return ne.getStringValue();
-			}
-			if (value instanceof StringEval) {
-				StringEval se = (StringEval) value;
-				return "'" + se.getStringValue() + "'";
-			}
-			if (value instanceof BoolEval) {
-				BoolEval be = (BoolEval) value;
-				return be.getStringValue();
-			}
-			if (value == BlankEval.instance) {
-				return "#BLANK#";
-			}
-			if (value instanceof ErrorEval) {
-				ErrorEval ee = (ErrorEval) value;
-				return ErrorEval.getText(ee.getErrorCode());
-			}
-			throw new IllegalArgumentException("Unexpected value class ("
-					+ value.getClass().getName() + ")");
-		}
-		public String[] getAndClearLog() {
-			String[] result = new String[_logList.size()];
-			_logList.toArray(result);
-			_logList.clear();
-			return result;
-		}
-	}
-	/**
-	 * Wrapper class to manage repetitive tasks from this test,
-	 *
-	 * Note - this class does a little bit more than just plain set-up of data. The method
-	 * {@link WorkbookEvaluator#clearCachedResultValue(HSSFSheet, int, int)} is called whenever
a
-	 * cell value is changed.
-	 *
-	 */
-	private static final class MySheet {
-
-		private final HSSFSheet _sheet;
-		private final WorkbookEvaluator _evaluator;
-		private final HSSFWorkbook _wb;
-		private final EvalListener _evalListener;
-
-		public MySheet() {
-			_wb = new HSSFWorkbook();
-			_evalListener = new EvalListener(_wb);
-			_evaluator = WorkbookEvaluatorTestHelper.createEvaluator(_wb, _evalListener);
-			_sheet = _wb.createSheet("Sheet1");
-		}
-
-		private static EvaluationCell wrapCell(HSSFCell cell) {
-			return HSSFEvaluationTestHelper.wrapCell(cell);
-		}
-
-		public void setCellValue(String cellRefText, double value) {
-			HSSFCell cell = getOrCreateCell(cellRefText);
-			// be sure to blank cell, in case it is currently a formula
-			cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
-			// otherwise this line will only set the formula cached result;
-			cell.setCellValue(value);
-			_evaluator.notifyUpdateCell(wrapCell(cell));
-		}
-		public void clearCell(String cellRefText) {
-			HSSFCell cell = getOrCreateCell(cellRefText);
-			cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
-			_evaluator.notifyUpdateCell(wrapCell(cell));
-		}
-
-		public void setCellFormula(String cellRefText, String formulaText) {
-			HSSFCell cell = getOrCreateCell(cellRefText);
-			cell.setCellFormula(formulaText);
-			_evaluator.notifyUpdateCell(wrapCell(cell));
-		}
-
-		private HSSFCell getOrCreateCell(String cellRefText) {
-			CellReference cr = new CellReference(cellRefText);
-			int rowIndex = cr.getRow();
-			HSSFRow row = _sheet.getRow(rowIndex);
-			if (row == null) {
-				row = _sheet.createRow(rowIndex);
-			}
-			int cellIndex = cr.getCol();
-			HSSFCell cell = row.getCell(cellIndex);
-			if (cell == null) {
-				cell = row.createCell(cellIndex);
-			}
-			return cell;
-		}
-
-		public ValueEval evaluateCell(String cellRefText) {
-			return _evaluator.evaluate(wrapCell(getOrCreateCell(cellRefText)));
-		}
-
-		public String[] getAndClearLog() {
-			return _evalListener.getAndClearLog();
-		}
-
-		public void clearAllCachedResultValues() {
-			_evaluator.clearAllCachedResultValues();
-		}
-	}
-
-	private static MySheet createMediumComplex() {
-		MySheet ms = new MySheet();
-
-		// plain data in D1:F3
-		ms.setCellValue("D1", 12);
-		ms.setCellValue("E1", 13);
-		ms.setCellValue("D2", 14);
-		ms.setCellValue("E2", 15);
-		ms.setCellValue("D3", 16);
-		ms.setCellValue("E3", 17);
-
-
-		ms.setCellFormula("C1", "SUM(D1:E2)");
-		ms.setCellFormula("C2", "SUM(D2:E3)");
-		ms.setCellFormula("C3", "SUM(D3:E4)");
-
-		ms.setCellFormula("B1", "C2-C1");
-		ms.setCellFormula("B2", "B3*C1-C2");
-		ms.setCellValue("B3", 2);
-
-		ms.setCellFormula("A1", "MAX(B1:B2)");
-		ms.setCellFormula("A2", "MIN(B3,D2:F2)");
-		ms.setCellFormula("A3", "B3*C3");
-
-		// clear all the logging from the above initialisation
-		ms.getAndClearLog();
-		ms.clearAllCachedResultValues();
-		return ms;
-	}
-
-	public void testMediumComplex() {
-
-		MySheet ms = createMediumComplex();
-		// completely fresh evaluation
-		confirmEvaluate(ms, "A1", 46);
-		confirmLog(ms, new String[] {
-			"start A1 MAX(B1:B2)",
-				"start B1 C2-C1",
-					"start C2 SUM(D2:E3)",
-						"value D2 14", "value E2 15", "value D3 16", "value E3 17",
-					"end C2 62",
-					"start C1 SUM(D1:E2)",
-						"value D1 12", "value E1 13", "hit D2 14", "hit E2 15",
-					"end C1 54",
-				"end B1 8",
-				"start B2 B3*C1-C2",
-					"value B3 2",
-					"hit C1 54",
-					"hit C2 62",
-				"end B2 46",
-			"end A1 46",
-		});
-
-
-		// simple cache hit - immediate re-evaluation with no changes
-		confirmEvaluate(ms, "A1", 46);
-		confirmLog(ms, new String[] { "hit A1 46", });
-
-		// change a low level cell
-		ms.setCellValue("D1", 10);
-		confirmLog(ms, new String[] {
-				"clear D1 10",
-				"clear1 C1 54",
-				"clear2 B1 8",
-				"clear3 A1 46",
-				"clear2 B2 46",
-		});
-		confirmEvaluate(ms, "A1", 42);
-		confirmLog(ms, new String[] {
-			"start A1 MAX(B1:B2)",
-				"start B1 C2-C1",
-					"hit C2 62",
-					"start C1 SUM(D1:E2)",
-						"hit D1 10", "hit E1 13", "hit D2 14", "hit E2 15",
-					"end C1 52",
-				"end B1 10",
-				"start B2 B3*C1-C2",
-					"hit B3 2",
-					"hit C1 52",
-					"hit C2 62",
-				"end B2 42",
-			"end A1 42",
-		});
-
-		// Reset and try changing an intermediate value
-		ms = createMediumComplex();
-		confirmEvaluate(ms, "A1", 46);
-		ms.getAndClearLog();
-
-		ms.setCellValue("B3", 3); // B3 is in the middle of the dependency tree
-		confirmLog(ms, new String[] {
-				"clear B3 3",
-				"clear1 B2 46",
-				"clear2 A1 46",
-		});
-		confirmEvaluate(ms, "A1", 100);
-		confirmLog(ms, new String[] {
-			"start A1 MAX(B1:B2)",
-				"hit B1 8",
-				"start B2 B3*C1-C2",
-					"hit B3 3",
-					"hit C1 54",
-					"hit C2 62",
-				"end B2 100",
-			"end A1 100",
-		});
-	}
-
-	public void testMediumComplexWithDependencyChange() {
-
-		// Changing an intermediate formula
-		MySheet ms = createMediumComplex();
-		confirmEvaluate(ms, "A1", 46);
-		ms.getAndClearLog();
-		ms.setCellFormula("B2", "B3*C2-C3"); // used to be "B3*C1-C2"
-		confirmLog(ms, new String[] {
-			"clear B2 46",
-			"clear1 A1 46",
-		});
-
-		confirmEvaluate(ms, "A1", 91);
-		confirmLog(ms, new String[] {
-			"start A1 MAX(B1:B2)",
-				"hit B1 8",
-				"start B2 B3*C2-C3",
-					"hit B3 2",
-					"hit C2 62",
-					"start C3 SUM(D3:E4)",
-						"hit D3 16", "hit E3 17",
-//						"value D4 #BLANK#", "value E4 #BLANK#",
-					"end C3 33",
-				"end B2 91",
-			"end A1 91",
-		});
-
-		//----------------
-		// Note - From now on the demonstrated POI behaviour is not optimal
-		//----------------
-
-		// Now change a value that should no longer affect B2
-		ms.setCellValue("D1", 11);
-		confirmLog(ms, new String[] {
-			"clear D1 11",
-			"clear1 C1 54",
-			// note there is no "clear2 B2 91" here because B2 doesn't depend on C1 anymore
-			"clear2 B1 8",
-			"clear3 A1 91",
-		});
-
-		confirmEvaluate(ms, "B2", 91);
-		confirmLog(ms, new String[] {
-			"hit B2 91",  // further confirmation that B2 was not cleared due to changing D1 above
-		});
-
-		// things should be back to normal now
-		ms.setCellValue("D1", 11);
-		confirmLog(ms, new String[] {  });
-		confirmEvaluate(ms, "B2", 91);
-		confirmLog(ms, new String[] {
-			"hit B2 91",
-		});
-	}
-
-	/**
-	 * verifies that when updating a plain cell, depending (formula) cell cached values are
cleared
-	 * only when the plain cell's value actually changes
-	 */
-	public void testRedundantUpdate() {
-		MySheet ms = new MySheet();
-
-		ms.setCellValue("B1", 12);
-		ms.setCellValue("C1", 13);
-		ms.setCellFormula("A1", "B1+C1");
-
-		// evaluate twice to confirm caching looks OK
-		ms.evaluateCell("A1");
-		ms.getAndClearLog();
-		confirmEvaluate(ms, "A1", 25);
-		confirmLog(ms, new String[] {
-			"hit A1 25",
-		});
-
-		// Make redundant update, and check re-evaluation
-		ms.setCellValue("B1", 12); // value didn't change
-		confirmLog(ms, new String[] {});
-		confirmEvaluate(ms, "A1", 25);
-		confirmLog(ms, new String[] {
-			"hit A1 25",
-		});
-
-		ms.setCellValue("B1", 11); // value changing
-		confirmLog(ms, new String[] {
-			"clear B1 11",
-			"clear1 A1 25",	// expect consuming formula cached result to get cleared
-		});
-		confirmEvaluate(ms, "A1", 24);
-		confirmLog(ms, new String[] {
-			"start A1 B1+C1",
-			"hit B1 11",
-			"hit C1 13",
-			"end A1 24",
-		});
-	}
-
-	/**
-	 * Changing any input to a formula may cause the formula to 'use' a different set of cells.
-	 * Functions like INDEX and OFFSET make this effect obvious, with functions like MATCH
-	 * and VLOOKUP the effect can be subtle.  The presence of error values can also produce
this
-	 * effect in almost every function and operator.
-	 */
-	public void testSimpleWithDependencyChange() {
-
-		MySheet ms = new MySheet();
-
-		ms.setCellFormula("A1", "INDEX(C1:E1,1,B1)");
-		ms.setCellValue("B1", 1);
-		ms.setCellValue("C1", 17);
-		ms.setCellValue("D1", 18);
-		ms.setCellValue("E1", 19);
-		ms.clearAllCachedResultValues();
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 17);
-		confirmLog(ms, new String[] {
-			"start A1 INDEX(C1:E1,1,B1)",
-			"value B1 1",
-			"value C1 17",
-			"end A1 17",
-		});
-		ms.setCellValue("B1", 2);
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 18);
-		confirmLog(ms, new String[] {
-			"start A1 INDEX(C1:E1,1,B1)",
-			"hit B1 2",
-			"value D1 18",
-			"end A1 18",
-		});
-
-		// change C1. Note - last time A1 evaluated C1 was not used
-		ms.setCellValue("C1", 15);
-		ms.getAndClearLog();
-		confirmEvaluate(ms, "A1", 18);
-		confirmLog(ms, new String[] {
-			"hit A1 18",
-		});
-
-		// but A1 still uses D1, so if it changes...
-		ms.setCellValue("D1", 25);
-		ms.getAndClearLog();
-		confirmEvaluate(ms, "A1", 25);
-		confirmLog(ms, new String[] {
-			"start A1 INDEX(C1:E1,1,B1)",
-			"hit B1 2",
-			"hit D1 25",
-			"end A1 25",
-		});
-	}
-
-	public void testBlankCells() {
-
-
-		MySheet ms = new MySheet();
-
-		ms.setCellFormula("A1", "sum(B1:D4,B5:E6)");
-		ms.setCellValue("B1", 12);
-		ms.clearAllCachedResultValues();
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 12);
-		confirmLog(ms, new String[] {
-			"start A1 SUM(B1:D4,B5:E6)",
-			"value B1 12",
-			"end A1 12",
-		});
-		ms.setCellValue("B6", 2);
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 14);
-		confirmLog(ms, new String[] {
-			"start A1 SUM(B1:D4,B5:E6)",
-			"hit B1 12",
-			"hit B6 2",
-			"end A1 14",
-		});
-		ms.setCellValue("E4", 2);
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 14);
-		confirmLog(ms, new String[] {
-			"hit A1 14",
-		});
-
-		ms.setCellValue("D1", 1);
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 15);
-		confirmLog(ms, new String[] {
-			"start A1 SUM(B1:D4,B5:E6)",
-			"hit B1 12",
-			"hit D1 1",
-			"hit B6 2",
-			"end A1 15",
-		});
-	}
-
-	/**
-	 * Make sure that when blank cells are changed to value/formula cells, any dependent formulas
-	 * have their cached results cleared.
-	 */
-	public void testBlankCellChangedToValueCell_bug46053() {
-		HSSFWorkbook wb = new HSSFWorkbook();
-		HSSFSheet sheet = wb.createSheet("Sheet1");
-		HSSFRow row = sheet.createRow(0);
-		HSSFCell cellA1 = row.createCell(0);
-		HSSFCell cellB1 = row.createCell(1);
-		HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
-
-		cellA1.setCellFormula("B1+2.2");
-		cellB1.setCellValue(1.5);
-
-		fe.notifyUpdateCell(cellA1);
-		fe.notifyUpdateCell(cellB1);
-
-		CellValue cv;
-		cv = fe.evaluate(cellA1);
-		assertEquals(3.7, cv.getNumberValue(), 0.0);
-
-		cellB1.setCellType(HSSFCell.CELL_TYPE_BLANK);
-		fe.notifyUpdateCell(cellB1);
-		cv = fe.evaluate(cellA1); // B1 was used to evaluate A1
-		assertEquals(2.2, cv.getNumberValue(), 0.0);
-
-		cellB1.setCellValue(0.4);  // changing B1, so A1 cached result should be cleared
-		fe.notifyUpdateCell(cellB1);
-		cv = fe.evaluate(cellA1);
-		if (cv.getNumberValue() == 2.2) {
-			// looks like left-over cached result from before change to B1
-			throw new AssertionFailedError("Identified bug 46053");
-		}
-		assertEquals(2.6, cv.getNumberValue(), 0.0);
-	}
-
-	/**
-	 * same use-case as the test for bug 46053, but checking trace values too
-	 */
-	public void testBlankCellChangedToValueCell() {
-
-		MySheet ms = new MySheet();
-
-		ms.setCellFormula("A1", "B1+2.2");
-		ms.setCellValue("B1", 1.5);
-		ms.clearAllCachedResultValues();
-		ms.clearCell("B1");
-		ms.getAndClearLog();
-
-		confirmEvaluate(ms, "A1", 2.2);
-		confirmLog(ms, new String[] {
-			"start A1 B1+2.2",
-			"end A1 2.2",
-		});
-		ms.setCellValue("B1", 0.4);
-		confirmLog(ms, new String[] {
-			"changeFromBlank B1 0.4",
-			"clear A1",
-		});
-
-		confirmEvaluate(ms, "A1", 2.6);
-		confirmLog(ms, new String[] {
-			"start A1 B1+2.2",
-			"hit B1 0.4",
-			"end A1 2.6",
-		});
-	}
-
-	private static void confirmEvaluate(MySheet ms, String cellRefText, double expectedValue)
{
-		ValueEval v = ms.evaluateCell(cellRefText);
-		assertEquals(NumberEval.class, v.getClass());
-		assertEquals(expectedValue, ((NumberEval)v).getNumberValue(), 0.0);
-	}
-
-	private static void confirmLog(MySheet ms, String[] expectedLog) {
-		String[] actualLog = ms.getAndClearLog();
-		int endIx = actualLog.length;
-		PrintStream ps = System.err;
-		if (endIx != expectedLog.length) {
-			ps.println("Log lengths mismatch");
-			dumpCompare(ps, expectedLog, actualLog);
-			throw new AssertionFailedError("Log lengths mismatch");
-		}
-		for (int i=0; i< endIx; i++) {
-			if (!actualLog[i].equals(expectedLog[i])) {
-				String msg = "Log entry mismatch at index " + i;
-				ps.println(msg);
-				dumpCompare(ps, expectedLog, actualLog);
-				throw new AssertionFailedError(msg);
-			}
-		}
-
-	}
-
-	private static void dumpCompare(PrintStream ps, String[] expectedLog, String[] actualLog)
{
-		int max = Math.max(actualLog.length, expectedLog.length);
-		ps.println("Index\tExpected\tActual");
-		for(int i=0; i<max; i++) {
-			ps.print(i + "\t");
-			printItem(ps, expectedLog, i);
-			ps.print("\t");
-			printItem(ps, actualLog, i);
-			ps.println();
-		}
-		ps.println();
-		debugPrint(ps, actualLog);
-	}
+public class TestPlainCellCache extends TestCase {
 
-	private static void printItem(PrintStream ps, String[] ss, int index) {
-		if (index < ss.length) {
-			ps.print(ss[index]);
-		}
-	}
+    /**
+     *
+     */
+    public void testLoc(){
+        PlainCellCache cache = new PlainCellCache();
+        for (int bookIndex = 0; bookIndex < 0x1000; bookIndex += 0x100) {
+            for (int sheetIndex = 0; sheetIndex < 0x1000; sheetIndex += 0x100) {
+                for (int rowIndex = 0; rowIndex < 0x100000; rowIndex += 0x1000) {
+                    for (int columnIndex = 0; columnIndex < 0x4000; columnIndex += 0x100)
{
+                        Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+                        assertEquals(bookIndex, loc.getBookIndex());
+                        assertEquals(sheetIndex, loc.getSheetIndex());
+                        assertEquals(rowIndex, loc.getRowIndex());
+                        assertEquals(columnIndex, loc.getColumnIndex());
+
+                        Loc sameLoc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+                        assertEquals(loc.hashCode(), sameLoc.hashCode());
+                        assertTrue(loc.equals(sameLoc));
+
+                        assertNull(cache.get(loc));
+                        PlainValueCellCacheEntry entry = new PlainValueCellCacheEntry(new
NumberEval(0));
+                        cache.put(loc, entry);
+                        assertSame(entry, cache.get(loc));
+                        cache.remove(loc);
+                        assertNull(cache.get(loc));
+
+                        cache.put(loc, entry);
+                    }
+                    cache.clear();
+                }
+            }
 
-	private static void debugPrint(PrintStream ps, String[] log) {
-		for (int i = 0; i < log.length; i++) {
-			ps.println('"' + log[i] + "\",");
-		}
-	}
+        }
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message