| /* ==================================================================== |
| 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; |
| |
| import org.apache.poi.ss.formula.ptg.AttrPtg; |
| import org.apache.poi.ss.formula.ptg.FuncVarPtg; |
| import org.apache.poi.ss.formula.ptg.IntPtg; |
| import org.apache.poi.ss.formula.ptg.Ptg; |
| import org.apache.poi.ss.formula.ptg.RefPtg; |
| import org.apache.poi.ss.usermodel.CellType; |
| import org.apache.poi.ss.usermodel.FormulaError; |
| |
| import junit.framework.AssertionFailedError; |
| import junit.framework.TestCase; |
| |
| /** |
| * Tests for {@link FormulaRecord} |
| * |
| * @author Andrew C. Oliver |
| */ |
| public final class TestFormulaRecord extends TestCase { |
| |
| public void testCreateFormulaRecord () { |
| FormulaRecord record = new FormulaRecord(); |
| record.setColumn((short)0); |
| record.setRow(1); |
| record.setXFIndex((short)4); |
| |
| assertEquals(record.getColumn(),0); |
| assertEquals(record.getRow(), 1); |
| assertEquals(record.getXFIndex(),4); |
| } |
| |
| /** |
| * Make sure a NAN value is preserved |
| * This formula record is a representation of =1/0 at row 0, column 0 |
| */ |
| public void testCheckNanPreserve() { |
| byte[] formulaByte = { |
| 0, 0, 0, 0, |
| 0x0F, 0x00, |
| |
| // 8 bytes cached number is a 'special value' in this case |
| 0x02, // special cached value type 'error' |
| 0x00, |
| FormulaError.DIV0.getCode(), |
| 0x00, |
| 0x00, |
| 0x00, |
| (byte)0xFF, |
| (byte)0xFF, |
| |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| |
| (byte)0xE0, //18 |
| (byte)0xFC, |
| // Ptgs |
| 0x07, 0x00, // encoded length |
| 0x1E, 0x01, 0x00, // IntPtg(1) |
| 0x1E, 0x00, 0x00, // IntPtg(0) |
| 0x06, // DividePtg |
| |
| }; |
| |
| FormulaRecord record = new FormulaRecord(TestcaseRecordInputStream.create(FormulaRecord.sid, formulaByte)); |
| assertEquals("Row", 0, record.getRow()); |
| assertEquals("Column", 0, record.getColumn()); |
| assertEquals(CellType.ERROR.getCode(), record.getCachedResultType()); |
| |
| byte[] output = record.serialize(); |
| assertEquals("Output size", 33, output.length); //includes sid+recordlength |
| |
| for (int i = 5; i < 13;i++) { |
| assertEquals("FormulaByte NaN doesn't match", formulaByte[i], output[i+4]); |
| } |
| } |
| |
| /** |
| * Tests to see if the shared formula cells properly reserialize the expPtg |
| * |
| */ |
| public void testExpFormula() { |
| byte[] formulaByte = new byte[27]; |
| |
| formulaByte[4] =(byte)0x0F; |
| formulaByte[14]=(byte)0x08; |
| formulaByte[18]=(byte)0xE0; |
| formulaByte[19]=(byte)0xFD; |
| formulaByte[20]=(byte)0x05; |
| formulaByte[22]=(byte)0x01; |
| FormulaRecord record = new FormulaRecord(TestcaseRecordInputStream.create(FormulaRecord.sid, formulaByte)); |
| assertEquals("Row", 0, record.getRow()); |
| assertEquals("Column", 0, record.getColumn()); |
| byte[] output = record.serialize(); |
| assertEquals("Output size", 31, output.length); //includes sid+recordlength |
| assertEquals("Offset 22", 1, output[26]); |
| } |
| |
| public void testWithConcat() { |
| // =CHOOSE(2,A2,A3,A4) |
| byte[] data = { |
| 1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 57, |
| 64, 0, 0, 12, 0, 12, -4, 46, 0, |
| 30, 2, 0, // Int - 2 |
| 25, 4, 3, 0, // Attr |
| 8, 0, 17, 0, 26, 0, // jumpTable |
| 35, 0, // chooseOffset |
| 36, 1, 0, 0, -64, // Ref - A2 |
| 25, 8, 21, 0, // Attr |
| 36, 2, 0, 0, -64, // Ref - A3 |
| 25, 8, 12, 0, // Attr |
| 36, 3, 0, 0, -64, // Ref - A4 |
| 25, 8, 3, 0, // Attr |
| 66, 4, 100, 0 // CHOOSE |
| }; |
| RecordInputStream inp = TestcaseRecordInputStream.create(FormatRecord.sid, data); |
| |
| FormulaRecord fr = new FormulaRecord(inp); |
| |
| Ptg[] ptgs = fr.getParsedExpression(); |
| assertEquals(9, ptgs.length); |
| assertEquals(IntPtg.class, ptgs[0].getClass()); |
| assertEquals(AttrPtg.class, ptgs[1].getClass()); |
| assertEquals(RefPtg.class, ptgs[2].getClass()); |
| assertEquals(AttrPtg.class, ptgs[3].getClass()); |
| assertEquals(RefPtg.class, ptgs[4].getClass()); |
| assertEquals(AttrPtg.class, ptgs[5].getClass()); |
| assertEquals(RefPtg.class, ptgs[6].getClass()); |
| assertEquals(AttrPtg.class, ptgs[7].getClass()); |
| assertEquals(FuncVarPtg.class, ptgs[8].getClass()); |
| |
| FuncVarPtg choose = (FuncVarPtg)ptgs[8]; |
| assertEquals("CHOOSE", choose.getName()); |
| } |
| |
| public void testReserialize() { |
| FormulaRecord formulaRecord = new FormulaRecord(); |
| formulaRecord.setRow(1); |
| formulaRecord.setColumn((short) 1); |
| formulaRecord.setParsedExpression(new Ptg[] { new RefPtg("B$5"), }); |
| formulaRecord.setValue(3.3); |
| byte[] ser = formulaRecord.serialize(); |
| assertEquals(31, ser.length); |
| |
| RecordInputStream in = TestcaseRecordInputStream.create(ser); |
| FormulaRecord fr2 = new FormulaRecord(in); |
| assertEquals(3.3, fr2.getValue(), 0.0); |
| Ptg[] ptgs = fr2.getParsedExpression(); |
| assertEquals(1, ptgs.length); |
| RefPtg rp = (RefPtg) ptgs[0]; |
| assertEquals("B$5", rp.toFormulaString()); |
| } |
| |
| /** |
| * Bug noticed while fixing 46479. Operands of conditional operator ( ? : ) were swapped |
| * inside {@link FormulaRecord} |
| */ |
| public void testCachedValue_bug46479() { |
| FormulaRecord fr0 = new FormulaRecord(); |
| FormulaRecord fr1 = new FormulaRecord(); |
| // test some other cached value types |
| fr0.setValue(3.5); |
| assertEquals(3.5, fr0.getValue(), 0.0); |
| fr0.setCachedResultErrorCode(FormulaError.REF.getCode()); |
| assertEquals(FormulaError.REF.getCode(), fr0.getCachedErrorValue()); |
| |
| fr0.setCachedResultBoolean(false); |
| fr1.setCachedResultBoolean(true); |
| if (fr0.getCachedBooleanValue() == true && fr1.getCachedBooleanValue() == false) { |
| throw new AssertionFailedError("Identified bug 46479c"); |
| } |
| assertEquals(false, fr0.getCachedBooleanValue()); |
| assertEquals(true, fr1.getCachedBooleanValue()); |
| } |
| } |