diff options
author | Josh Micich <josh@apache.org> | 2008-10-26 06:40:36 +0000 |
---|---|---|
committer | Josh Micich <josh@apache.org> | 2008-10-26 06:40:36 +0000 |
commit | 063dd2ad03e30263b45167615cddb69dd9189584 (patch) | |
tree | 8ecbe039c21e44bac69636eb51d30b4efe7bec22 /src/testcases/org | |
parent | acfcbeb3c568b596bd052edca73d448e2f9b5b3d (diff) | |
download | poi-063dd2ad03e30263b45167615cddb69dd9189584.tar.gz poi-063dd2ad03e30263b45167615cddb69dd9189584.zip |
Merged revisions 706772,707450,707481 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk
........
r706772 | josh | 2008-10-21 14:25:50 -0700 (Tue, 21 Oct 2008) | 1 line
Fix for bug 46053 - fixed evaluation cache dependency analysis when changing blank cells
........
r707450 | josh | 2008-10-23 12:08:42 -0700 (Thu, 23 Oct 2008) | 1 line
Fix for bug 45778 - made ObjRecord read sub-record ftLbsData properly
........
r707481 | josh | 2008-10-23 14:42:05 -0700 (Thu, 23 Oct 2008) | 1 line
fixed re-serialization of tAttrChoose
........
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@707942 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/testcases/org')
11 files changed, 335 insertions, 132 deletions
diff --git a/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java index ad629c3f17..53a49fda0d 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java @@ -21,56 +21,54 @@ package org.apache.poi.hssf.record; import junit.framework.TestCase; /** - * Tests the serialization and deserialization of the CommonObjectDataSubRecord + * Tests the serialization and deserialization of the {@link CommonObjectDataSubRecord} * class works correctly. Test data taken directly from a real * Excel file. * - * @author Glen Stampoultzis (glens at apache.org) */ public final class TestCommonObjectDataSubRecord extends TestCase { - byte[] data = new byte[] { - (byte)0x12,(byte)0x00,(byte)0x01,(byte)0x00, - (byte)0x01,(byte)0x00,(byte)0x11,(byte)0x60, - (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, - (byte)0x00,(byte)0x0D,(byte)0x26,(byte)0x01, - (byte)0x00,(byte)0x00, - }; + byte[] data = new byte[] { + (byte)0x12,(byte)0x00,(byte)0x01,(byte)0x00, + (byte)0x01,(byte)0x00,(byte)0x11,(byte)0x60, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x0D,(byte)0x26,(byte)0x01, + (byte)0x00,(byte)0x00, + }; - public void testLoad() { - CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(TestcaseRecordInputStream.create(0x15, data)); + public void testLoad() { + CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(TestcaseRecordInputStream.createWithFakeSid(data), data.length); - assertEquals( CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX, record.getObjectType()); - assertEquals( (short)1, record.getObjectId()); - assertEquals( (short)1, record.getOption()); - assertEquals( true , record.isLocked() ); - assertEquals( false, record.isPrintable() ); - assertEquals( false, record.isAutofill() ); - assertEquals( false, record.isAutoline() ); - assertEquals( (int)24593, record.getReserved1()); - assertEquals( (int)218103808, record.getReserved2()); - assertEquals( (int)294, record.getReserved3()); - assertEquals( 22 , record.getRecordSize() ); - } + assertEquals( CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX, record.getObjectType()); + assertEquals((short) 1, record.getObjectId()); + assertEquals((short) 1, record.getOption()); + assertEquals(true, record.isLocked()); + assertEquals(false, record.isPrintable()); + assertEquals(false, record.isAutofill()); + assertEquals(false, record.isAutoline()); + assertEquals(24593, record.getReserved1()); + assertEquals(218103808, record.getReserved2()); + assertEquals(294, record.getReserved3()); + assertEquals(18, record.getDataSize()); + } - public void testStore() - { - CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(); + public void testStore() { + CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(); - record.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX ); - record.setObjectId( (short) 1); - record.setOption( (short) 1); - record.setLocked( true ); - record.setPrintable( false ); - record.setAutofill( false ); - record.setAutoline( false ); - record.setReserved1( (int) 24593); - record.setReserved2( (int) 218103808); - record.setReserved3( (int) 294); + record.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX); + record.setObjectId((short) 1); + record.setOption((short) 1); + record.setLocked(true); + record.setPrintable(false); + record.setAutofill(false); + record.setAutoline(false); + record.setReserved1(24593); + record.setReserved2(218103808); + record.setReserved3(294); - byte [] recordBytes = record.serialize(); - assertEquals(recordBytes.length - 4, data.length); - for (int i = 0; i < data.length; i++) - assertEquals("At offset " + i, data[i], recordBytes[i+4]); - } + byte [] recordBytes = record.serialize(); + assertEquals(recordBytes.length - 4, data.length); + for (int i = 0; i < data.length; i++) + assertEquals("At offset " + i, data[i], recordBytes[i+4]); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java index bf8da6fece..deaf779bbb 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java @@ -42,13 +42,13 @@ public final class TestEmbeddedObjectRefSubRecord extends TestCase { RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(src));
in.nextRecord();
- EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord(in);
+ EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord(in, src.length-4);
byte[] ser = record1.serialize();
RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));
in2.nextRecord();
- EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2);
+ EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2, ser.length-4);
assertTrue(Arrays.equals(src, ser));
assertEquals(record1.getOLEClassName(), record2.getOLEClassName());
@@ -64,7 +64,7 @@ public final class TestEmbeddedObjectRefSubRecord extends TestCase { byte[] ser = record1.serialize();
RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));
in2.nextRecord();
- EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2);
+ EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2, ser.length-4);
assertEquals(record1.getOLEClassName(), record2.getOLEClassName());
assertEquals(record1.getStreamId(), record2.getStreamId());
@@ -88,7 +88,7 @@ public final class TestEmbeddedObjectRefSubRecord extends TestCase { RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
in.nextRecord();
- EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in);
+ EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in, data.length-4);
byte[] ser2 = rec.serialize();
assertTrue(Arrays.equals(data, ser2));
@@ -129,7 +129,7 @@ public final class TestEmbeddedObjectRefSubRecord extends TestCase { private static void confirmRead(byte[] data, int i) {
RecordInputStream in = TestcaseRecordInputStream.create(EmbeddedObjectRefSubRecord.sid, data);
- EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in);
+ EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in, data.length);
byte[] ser2 = rec.serialize();
byte[] d2 = (byte[]) data.clone(); // remove sid+len for compare
System.arraycopy(ser2, 4, d2, 0, d2.length);
diff --git a/src/testcases/org/apache/poi/hssf/record/TestEndSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestEndSubRecord.java index d16c227149..ab4a80120f 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestEndSubRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestEndSubRecord.java @@ -28,14 +28,11 @@ import junit.framework.TestCase; * @author Glen Stampoultzis (glens at apache.org) */ public final class TestEndSubRecord extends TestCase { - byte[] data = new byte[] { - - }; + private static final byte[] data = { }; public void testLoad() { - EndSubRecord record = new EndSubRecord(TestcaseRecordInputStream.create(0x00, data)); - - assertEquals( 4, record.getRecordSize() ); + EndSubRecord record = new EndSubRecord(TestcaseRecordInputStream.create(0x00, data), 0); + assertEquals(0, record.getDataSize()); } public void testStore() diff --git a/src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java index fd2ae059b7..ff93c90c24 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java @@ -38,16 +38,16 @@ public final class TestNoteStructureSubRecord extends TestCase { public void testRead() { - NoteStructureSubRecord record = new NoteStructureSubRecord(TestcaseRecordInputStream.create(NoteStructureSubRecord.sid, data)); + NoteStructureSubRecord record = new NoteStructureSubRecord(TestcaseRecordInputStream.create(NoteStructureSubRecord.sid, data), data.length); assertEquals(NoteStructureSubRecord.sid, record.getSid()); - assertEquals(data.length + 4, record.getRecordSize()); + assertEquals(data.length, record.getDataSize()); } public void testWrite() { NoteStructureSubRecord record = new NoteStructureSubRecord(); assertEquals(NoteStructureSubRecord.sid, record.getSid()); - assertEquals(data.length + 4, record.getRecordSize()); + assertEquals(data.length, record.getDataSize()); byte [] ser = record.serialize(); assertEquals(ser.length - 4, data.length); @@ -62,7 +62,7 @@ public final class TestNoteStructureSubRecord extends TestCase { NoteStructureSubRecord cloned = (NoteStructureSubRecord)record.clone(); byte[] cln = cloned.serialize(); - assertEquals(record.getRecordSize(), cloned.getRecordSize()); + assertEquals(record.getDataSize(), cloned.getDataSize()); assertTrue(Arrays.equals(src, cln)); } } diff --git a/src/testcases/org/apache/poi/hssf/record/TestObjRecord.java b/src/testcases/org/apache/poi/hssf/record/TestObjRecord.java index df26797807..c143120de8 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestObjRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestObjRecord.java @@ -41,19 +41,19 @@ public final class TestObjRecord extends TestCase { private static final byte[] recdata = { 0x15, 0x00, 0x12, 0x00, 0x06, 0x00, 0x01, 0x00, 0x11, 0x60, (byte)0xF4, 0x02, 0x41, 0x01, 0x14, 0x10, 0x1F, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TODO - this data seems to require two extra bytes padding. not sure where original file is. // it's not bug 38607 attachment 17639 }; private static final byte[] recdataNeedingPadding = { - 21, 0, 18, 0, 0, 0, 1, 0, 17, 96, 0, 0, 0, 0, 56, 111, -52, 3, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0 + 21, 0, 18, 0, 0, 0, 1, 0, 17, 96, 0, 0, 0, 0, 56, 111, -52, 3, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; public void testLoad() { ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata)); - assertEquals(28, record.getRecordSize() - 4); + assertEquals(26, record.getRecordSize() - 4); List subrecords = record.getSubRecords(); assertEquals(2, subrecords.size() ); @@ -66,7 +66,7 @@ public final class TestObjRecord extends TestCase { ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata)); byte [] recordBytes = record.serialize(); - assertEquals(28, recordBytes.length - 4); + assertEquals(26, recordBytes.length - 4); byte[] subData = new byte[recdata.length]; System.arraycopy(recordBytes, 4, subData, 0, subData.length); assertTrue(Arrays.equals(recdata, subData)); @@ -102,7 +102,7 @@ public final class TestObjRecord extends TestCase { ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdataNeedingPadding)); if (record.getRecordSize() == 34) { - throw new AssertionFailedError("Identified bug 45133"); + throw new AssertionFailedError("Identified bug 45133"); } assertEquals(36, record.getRecordSize()); diff --git a/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java index f8060b149a..9d0edd1c14 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java @@ -19,81 +19,94 @@ package org.apache.poi.hssf.record; +import java.util.Arrays; + +import junit.framework.AssertionFailedError; import junit.framework.TestCase; +import org.apache.poi.util.HexRead; + /** * Tests Subrecord components of an OBJ record. Test data taken directly * from a real Excel file. * * @author Michael Zalewski (zalewski@optonline.net) */ -public class TestSubRecord - extends TestCase -{ - /* - The following is a dump of the OBJ record corresponding to an auto-filter - drop-down list. The 3rd subrecord beginning at offset 0x002e (type=0x0013) - does not conform to the documentation, because the length field is 0x1fee, - which is longer than the entire OBJ record. - - 00000000 15 00 12 00 14 00 01 00 01 21 00 00 00 00 3C 13 .........!....<. Type=0x15 Len=0x0012 ftCmo - 00000010 F4 03 00 00 00 00 - 0C 00 14 00 00 00 00 00 00 00 ................ Type=0x0c Len=0x0014 ftSbs - 00000020 00 00 00 00 01 00 08 00 00 00 10 00 00 00 - 13 00 ................ Type=0x13 Len=0x1FEE ftLbsData - 00000030 EE 1F 00 00 08 00 08 00 01 03 00 00 0A 00 14 00 ................ - 00000040 6C 00 - 00 00 00 00 l..... Type=0x00 Len=0x0000 ftEnd - */ - - byte[] dataAutoFilter = new byte[]{ - // ftCmo - (byte) 0x15, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x00 - , (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x21, (byte) 0x00, (byte) 0x00, (byte) 0x3c, (byte) 0x13 - , (byte) 0xf4, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 - - // ftSbs (currently UnknownSubrecord) - , (byte) 0x0c, (byte) 0x00 - , (byte) 0x14, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 - , (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00 - , (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00 - - // ftLbsData (currently UnknownSubrecord) - , (byte) 0x13, (byte) 0x00 - , (byte) 0xee, (byte) 0x1f, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x08, (byte) 0x00 - , (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x14, (byte) 0x00 - , (byte) 0x6c, (byte) 0x00 - - // ftEnd - , (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 - }; - - public TestSubRecord( String name ) - { - super( name ); - } - - public void testParseCmo() - { -//jmh Record r = SubRecord.createSubRecord( (short) 0x0015, (short) 0x0012, dataAutoFilter, 0x0000 ); -//jmh assertEquals( "ftCmo is 22 bytes", 22, r.getRecordSize() ); -//jmh assertEquals( "ftCmo is a CommonObjectDataSubRecord" -//jmh , "org.apache.poi.hssf.record.CommonObjectDataSubRecord" -//jmh , r.getClass().getName() ); - } - - public void testParseAutoFilterLbsData() - { -//jmh Record r = SubRecord.createSubRecord( (short) 0x0013, (short) 0x1fee, dataAutoFilter, 0x0032 ); -//jmh assertEquals( "ftLbsData is 20 bytes", 20, r.getRecordSize() ); - } - - public void testParseEnd() - { -//jmh Record r = SubRecord.createSubRecord( (short) 0x0000, (short) 0x0000, dataAutoFilter, 0x0046 ); -//jmh assertEquals( "ftEnd is 4 bytes", 4, r.getRecordSize() ); -//jmh assertEquals( "ftEnd is a EndSubRecord" -//jmh , "org.apache.poi.hssf.record.EndSubRecord" -//jmh , r.getClass().getName() ); - } +public final class TestSubRecord extends TestCase { + /* + The following is a dump of the OBJ record corresponding to an auto-filter + drop-down list. The 3rd subrecord beginning at offset 0x002e (type=0x0013) + does not conform to the documentation, because the length field is 0x1fee, + which is longer than the entire OBJ record. + + 00000000 15 00 12 00 14 00 01 00 01 21 00 00 00 00 3C 13 .........!....<. Type=0x15 Len=0x0012 ftCmo + 00000010 F4 03 00 00 00 00 + 0C 00 14 00 00 00 00 00 00 00 ................ Type=0x0c Len=0x0014 ftSbs + 00000020 00 00 00 00 01 00 08 00 00 00 10 00 00 00 + 13 00 ................ Type=0x13 Len=0x1FEE ftLbsData + 00000030 EE 1F 00 00 08 00 08 00 01 03 00 00 0A 00 14 00 ................ + 00000040 6C 00 + 00 00 00 00 l..... Type=0x00 Len=0x0000 ftEnd + */ + + private static final byte[] dataAutoFilter + = HexRead.readFromString("" + + "5D 00 46 00 " // ObjRecord.sid, size=70 + // ftCmo + + "15 00 12 00 " + + "14 00 01 00 01 00 01 21 00 00 3C 13 F4 03 00 00 00 00 " + // ftSbs (currently UnknownSubrecord) + + "0C 00 14 00 " + + "00 00 00 00 00 00 00 00 00 00 01 00 08 00 00 00 10 00 00 00 " + // ftLbsData (currently UnknownSubrecord) + + "13 00 EE 1F 00 00 " + + "08 00 08 00 01 03 00 00 0A 00 14 00 6C 00 " + // ftEnd + + "00 00 00 00" + ); + + + /** + * Make sure that ftLbsData (which has abnormal size info) is parsed correctly. + * If the size field is interpreted incorrectly, the resulting ObjRecord becomes way too big. + * At the time of fixing (Oct-2008 svn r707447) {@link RecordInputStream} allowed buffer + * read overruns, so the bug was mostly silent. + */ + public void testReadAll_bug45778() { + RecordInputStream in = TestcaseRecordInputStream.create(dataAutoFilter); + ObjRecord or = new ObjRecord(in); + byte[] data2 = or.serialize(); + if (data2.length == 8228) { + throw new AssertionFailedError("Identified bug 45778"); + } + assertEquals(74, data2.length); + assertTrue(Arrays.equals(dataAutoFilter, data2)); + } + + public void testReadManualComboWithFormula() { + byte[] data = HexRead.readFromString("" + + "5D 00 66 00 " + + "15 00 12 00 14 00 02 00 11 20 00 00 00 00 " + + "20 44 C6 04 00 00 00 00 0C 00 14 00 04 F0 C6 04 " + + "00 00 00 00 00 00 01 00 06 00 00 00 10 00 00 00 " + + "0E 00 0C 00 05 00 80 44 C6 04 24 09 00 02 00 02 " + + "13 00 DE 1F 10 00 09 00 80 44 C6 04 25 0A 00 0F " + + "00 02 00 02 00 02 06 00 03 00 08 00 00 00 00 00 " + + "08 00 00 00 00 00 00 00 " // TODO sometimes last byte is non-zero + ); + + RecordInputStream in = TestcaseRecordInputStream.create(data); + ObjRecord or = new ObjRecord(in); + byte[] data2 = or.serialize(); + if (data2.length == 8228) { + throw new AssertionFailedError("Identified bug XXXXX"); + } + assertEquals("Encoded length", data.length, data2.length); + for (int i = 0; i < data.length; i++) { + if (data[i] != data2[i]) { + throw new AssertionFailedError("Encoded data differs at index " + i); + } + } + assertTrue(Arrays.equals(data, data2)); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java b/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java index 5f63f31a0b..248f7ca59d 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java @@ -41,6 +41,7 @@ public final class AllFormulaTests { result.addTestSuite(TestAreaErrPtg.class); result.addTestSuite(TestAreaPtg.class); result.addTestSuite(TestArrayPtg.class); + result.addTestSuite(TestAttrPtg.class); result.addTestSuite(TestErrPtg.class); result.addTestSuite(TestExternalFunctionFormulas.class); result.addTestSuite(TestFormulaShifter.class); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestAttrPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestAttrPtg.java new file mode 100644 index 0000000000..d9342d61c0 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestAttrPtg.java @@ -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.hssf.record.formula; + +import java.util.Arrays; + +import junit.framework.AssertionFailedError; + +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.hssf.record.TestcaseRecordInputStream; +import org.apache.poi.util.HexRead; + +/** + * Tests for {@link AttrPtg}. + * + * @author Josh Micich + */ +public final class TestAttrPtg extends AbstractPtgTestCase { + + /** + * Fix for bug visible around svn r706772. + */ + public void testReserializeAttrChoose() { + byte[] data = HexRead.readFromString("19, 04, 03, 00, 08, 00, 11, 00, 1A, 00, 23, 00"); + RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(data); + Ptg[] ptgs = Ptg.readTokens(data.length, in); + byte[] data2 = new byte[data.length]; + try { + Ptg.serializePtgs(ptgs, data2, 0); + } catch (ArrayIndexOutOfBoundsException e) { + throw new AssertionFailedError("incorrect re-serialization of tAttrChoose"); + } + assertTrue(Arrays.equals(data, data2)); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/EvaluationListener.java b/src/testcases/org/apache/poi/ss/formula/EvaluationListener.java index 46bb061722..1158c73b22 100644 --- a/src/testcases/org/apache/poi/ss/formula/EvaluationListener.java +++ b/src/testcases/org/apache/poi/ss/formula/EvaluationListener.java @@ -19,7 +19,6 @@ package org.apache.poi.ss.formula; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.usermodel.HSSFCell; /** * Tests should extend this class if they need to track the internal working of the {@link WorkbookEvaluator}.<br/> @@ -47,6 +46,10 @@ public abstract class EvaluationListener implements IEvaluationListener { public void onClearCachedValue(ICacheEntry entry) { // do nothing } + public void onChangeFromBlankValue(int sheetIndex, int rowIndex, int columnIndex, + EvaluationCell cell, ICacheEntry entry) { + // do nothing + } public void sortDependentCachedValues(ICacheEntry[] entries) { // do nothing } diff --git a/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java b/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java index 068c97a255..d42bfacd2d 100644 --- a/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java +++ b/src/testcases/org/apache/poi/ss/formula/TestEvaluationCache.java @@ -38,11 +38,13 @@ import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; 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.util.CellReference; import org.apache.poi.ss.formula.PlainCellCache.Loc; +import org.apache.poi.ss.usermodel.CellValue; /** * Tests {@link EvaluationCache}. Makes sure that where possible (previously calculated) cached @@ -134,7 +136,19 @@ public class TestEvaluationCache extends TestCase { } public void onClearDependentCachedValue(ICacheEntry entry, int depth) { EvaluationCell cell = (EvaluationCell) _formulaCellsByCacheEntry.get(entry); - log("clear" + depth, cell.getRowIndex(), cell.getColumnIndex(), entry.getValue()); + 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); @@ -213,6 +227,11 @@ public class TestEvaluationCache extends TestCase { 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); @@ -555,6 +574,75 @@ public class TestEvaluationCache extends TestCase { }); } + /** + * 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()); diff --git a/src/testcases/org/apache/poi/util/TestLittleEndianStreams.java b/src/testcases/org/apache/poi/util/TestLittleEndianStreams.java new file mode 100644 index 0000000000..b8fdf7a9d4 --- /dev/null +++ b/src/testcases/org/apache/poi/util/TestLittleEndianStreams.java @@ -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.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * Class to test {@link LittleEndianInputStream} and {@link LittleEndianOutputStream}
+ *
+ * @author Josh Micich
+ */
+public final class TestLittleEndianStreams extends TestCase {
+
+ public void testRead() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ LittleEndianOutput leo = new LittleEndianOutputStream(baos);
+ leo.writeInt(12345678);
+ leo.writeShort(12345);
+ leo.writeByte(123);
+ leo.writeShort(40000);
+ leo.writeByte(200);
+ leo.writeLong(1234567890123456789L);
+ leo.writeDouble(123.456);
+
+ LittleEndianInput lei = new LittleEndianInputStream(new ByteArrayInputStream(baos.toByteArray()));
+
+ assertEquals(12345678, lei.readInt());
+ assertEquals(12345, lei.readShort());
+ assertEquals(123, lei.readByte());
+ assertEquals(40000, lei.readUShort());
+ assertEquals(200, lei.readUByte());
+ assertEquals(1234567890123456789L, lei.readLong());
+ assertEquals(123.456, lei.readDouble(), 0.0);
+ }
+}
|