You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2021/05/22 20:56:49 UTC

svn commit: r1890120 [32/43] - in /poi/trunk/poi/src: main/java/org/apache/poi/ main/java/org/apache/poi/ddf/ main/java/org/apache/poi/extractor/ main/java/org/apache/poi/hpsf/ main/java/org/apache/poi/hssf/ main/java/org/apache/poi/hssf/dev/ main/java...

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestColumnInfoRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestColumnInfoRecordsAggregate.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestColumnInfoRecordsAggregate.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestColumnInfoRecordsAggregate.java Sat May 22 20:56:44 2021
@@ -29,99 +29,99 @@ import org.junit.jupiter.api.Test;
 
 final class TestColumnInfoRecordsAggregate {
 
-	@Test
+    @Test
     void testGetRecordSize() {
-		ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
-		agg.insertColumn(createColInfo(1, 3));
-		agg.insertColumn(createColInfo(4, 7));
-		agg.insertColumn(createColInfo(8, 8));
-		agg.groupColumnRange((short) 2, (short) 5, true);
-		assertEquals(4, agg.getNumColumns());
-
-		confirmSerializedSize(agg);
-
-		agg = new ColumnInfoRecordsAggregate();
-		agg.groupColumnRange((short) 3, (short) 6, true);
-		confirmSerializedSize(agg);
-	}
-
-	private static void confirmSerializedSize(RecordBase cirAgg) {
-		int estimatedSize = cirAgg.getRecordSize();
-		byte[] buf = new byte[estimatedSize];
-		int serializedSize = cirAgg.serialize(0, buf);
-		assertEquals(estimatedSize, serializedSize);
-	}
-
-	private static ColumnInfoRecord createColInfo(int firstCol, int lastCol) {
-		ColumnInfoRecord columnInfoRecord = new ColumnInfoRecord();
-		columnInfoRecord.setFirstColumn((short) firstCol);
-		columnInfoRecord.setLastColumn((short) lastCol);
-		return columnInfoRecord;
-	}
-
-	@Test
-	void testGroupColumns_bug45639() {
-		ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
-		agg.groupColumnRange( 7, 9, true);
-		agg.groupColumnRange( 4, 12, true);
-
-		// bug 45639 - ArrayIndexOutOfBoundsException
-		agg.groupColumnRange( 1, 15, true);
-
-		List<org.apache.poi.hssf.record.Record> cirs = new ArrayList<>();
-		agg.visitContainedRecords(cirs::add);
-
-		assertEquals(5, cirs.size());
-		confirmCIR(cirs, 0,  1,  3, 1, false, false);
-		confirmCIR(cirs, 1,  4,  6, 2, false, false);
-		confirmCIR(cirs, 2,  7,  9, 3, false, false);
-		confirmCIR(cirs, 3, 10, 12, 2, false, false);
-		confirmCIR(cirs, 4, 13, 15, 1, false, false);
-	}
-
-	/**
-	 * Check that an inner group remains hidden
-	 */
-	@Test
-	void testHiddenAfterExpanding() {
-		ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
-		agg.groupColumnRange(1, 15, true);
-		agg.groupColumnRange(4, 12, true);
-
-		List<org.apache.poi.hssf.record.Record> cirs = new ArrayList<>();
-
-		// collapse both inner and outer groups
-		agg.collapseColumn(6);
-		agg.collapseColumn(3);
-
-		agg.visitContainedRecords(cirs::add);
-		assertEquals(5, cirs.size());
-		confirmCIR(cirs, 0,  1,  3, 1, true, false);
-		confirmCIR(cirs, 1,  4, 12, 2, true, false);
-		confirmCIR(cirs, 2, 13, 13, 1, true, true);
-		confirmCIR(cirs, 3, 14, 15, 1, true, false);
-		confirmCIR(cirs, 4, 16, 16, 0, false, true);
-
-		// just expand the inner group
-		agg.expandColumn(6);
-
-		cirs.clear();
-		agg.visitContainedRecords(cirs::add);
-		assertEquals(4, cirs.size());
-		assertTrue(((ColumnInfoRecord)cirs.get(1)).getHidden(), "Inner group should still be hidden");
-		confirmCIR(cirs, 0,  1,  3, 1, true, false);
-		confirmCIR(cirs, 1,  4, 12, 2, true, false);
-		confirmCIR(cirs, 2, 13, 15, 1, true, false);
-		confirmCIR(cirs, 3, 16, 16, 0, false, true);
-	}
-
-	private static void confirmCIR(List<org.apache.poi.hssf.record.Record> cirs, int ix, int startColIx, int endColIx, int level, boolean isHidden, boolean isCollapsed) {
-		assertTrue(cirs.get(ix) instanceof ColumnInfoRecord);
-		ColumnInfoRecord cir = (ColumnInfoRecord)cirs.get(ix);
-		assertEquals(startColIx, cir.getFirstColumn(), "startColIx");
-		assertEquals(endColIx, cir.getLastColumn(), "endColIx");
-		assertEquals(level, cir.getOutlineLevel(), "level");
-		assertEquals(isHidden, cir.getHidden(), "hidden");
-		assertEquals(isCollapsed, cir.getCollapsed(), "collapsed");
-	}
+        ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
+        agg.insertColumn(createColInfo(1, 3));
+        agg.insertColumn(createColInfo(4, 7));
+        agg.insertColumn(createColInfo(8, 8));
+        agg.groupColumnRange((short) 2, (short) 5, true);
+        assertEquals(4, agg.getNumColumns());
+
+        confirmSerializedSize(agg);
+
+        agg = new ColumnInfoRecordsAggregate();
+        agg.groupColumnRange((short) 3, (short) 6, true);
+        confirmSerializedSize(agg);
+    }
+
+    private static void confirmSerializedSize(RecordBase cirAgg) {
+        int estimatedSize = cirAgg.getRecordSize();
+        byte[] buf = new byte[estimatedSize];
+        int serializedSize = cirAgg.serialize(0, buf);
+        assertEquals(estimatedSize, serializedSize);
+    }
+
+    private static ColumnInfoRecord createColInfo(int firstCol, int lastCol) {
+        ColumnInfoRecord columnInfoRecord = new ColumnInfoRecord();
+        columnInfoRecord.setFirstColumn((short) firstCol);
+        columnInfoRecord.setLastColumn((short) lastCol);
+        return columnInfoRecord;
+    }
+
+    @Test
+    void testGroupColumns_bug45639() {
+        ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
+        agg.groupColumnRange( 7, 9, true);
+        agg.groupColumnRange( 4, 12, true);
+
+        // bug 45639 - ArrayIndexOutOfBoundsException
+        agg.groupColumnRange( 1, 15, true);
+
+        List<org.apache.poi.hssf.record.Record> cirs = new ArrayList<>();
+        agg.visitContainedRecords(cirs::add);
+
+        assertEquals(5, cirs.size());
+        confirmCIR(cirs, 0,  1,  3, 1, false, false);
+        confirmCIR(cirs, 1,  4,  6, 2, false, false);
+        confirmCIR(cirs, 2,  7,  9, 3, false, false);
+        confirmCIR(cirs, 3, 10, 12, 2, false, false);
+        confirmCIR(cirs, 4, 13, 15, 1, false, false);
+    }
+
+    /**
+     * Check that an inner group remains hidden
+     */
+    @Test
+    void testHiddenAfterExpanding() {
+        ColumnInfoRecordsAggregate agg = new ColumnInfoRecordsAggregate();
+        agg.groupColumnRange(1, 15, true);
+        agg.groupColumnRange(4, 12, true);
+
+        List<org.apache.poi.hssf.record.Record> cirs = new ArrayList<>();
+
+        // collapse both inner and outer groups
+        agg.collapseColumn(6);
+        agg.collapseColumn(3);
+
+        agg.visitContainedRecords(cirs::add);
+        assertEquals(5, cirs.size());
+        confirmCIR(cirs, 0,  1,  3, 1, true, false);
+        confirmCIR(cirs, 1,  4, 12, 2, true, false);
+        confirmCIR(cirs, 2, 13, 13, 1, true, true);
+        confirmCIR(cirs, 3, 14, 15, 1, true, false);
+        confirmCIR(cirs, 4, 16, 16, 0, false, true);
+
+        // just expand the inner group
+        agg.expandColumn(6);
+
+        cirs.clear();
+        agg.visitContainedRecords(cirs::add);
+        assertEquals(4, cirs.size());
+        assertTrue(((ColumnInfoRecord)cirs.get(1)).getHidden(), "Inner group should still be hidden");
+        confirmCIR(cirs, 0,  1,  3, 1, true, false);
+        confirmCIR(cirs, 1,  4, 12, 2, true, false);
+        confirmCIR(cirs, 2, 13, 15, 1, true, false);
+        confirmCIR(cirs, 3, 16, 16, 0, false, true);
+    }
+
+    private static void confirmCIR(List<org.apache.poi.hssf.record.Record> cirs, int ix, int startColIx, int endColIx, int level, boolean isHidden, boolean isCollapsed) {
+        assertTrue(cirs.get(ix) instanceof ColumnInfoRecord);
+        ColumnInfoRecord cir = (ColumnInfoRecord)cirs.get(ix);
+        assertEquals(startColIx, cir.getFirstColumn(), "startColIx");
+        assertEquals(endColIx, cir.getLastColumn(), "endColIx");
+        assertEquals(level, cir.getOutlineLevel(), "level");
+        assertEquals(isHidden, cir.getHidden(), "hidden");
+        assertEquals(isCollapsed, cir.getCollapsed(), "collapsed");
+    }
 }

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestFormulaRecordAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestFormulaRecordAggregate.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestFormulaRecordAggregate.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestFormulaRecordAggregate.java Sat May 22 20:56:44 2021
@@ -36,62 +36,62 @@ import org.junit.jupiter.api.Test;
 
 final class TestFormulaRecordAggregate {
 
-	@Test
-	void testBasic() {
-		FormulaRecord f = new FormulaRecord();
-		f.setCachedResultTypeString();
-		StringRecord s = new StringRecord();
-		s.setString("abc");
-		FormulaRecordAggregate fagg = new FormulaRecordAggregate(f, s, SharedValueManager.createEmpty());
-		assertEquals("abc", fagg.getStringValue());
-		assertFalse(fagg.isPartOfArrayFormula());
-	}
-
-	/**
-	 * Sometimes a {@link StringRecord} appears after a {@link FormulaRecord} even though the
-	 * formula has evaluated to a text value.  This might be more likely to occur when the formula
-	 * <i>can</i> evaluate to a text value.<br>
-	 * Bug 46213 attachment 22874 has such an extra {@link StringRecord} at stream offset 0x5765.
-	 * This file seems to open in Excel (2007) with no trouble.  When it is re-saved, Excel omits
-	 * the extra record.  POI should do the same.
-	 */
-	@Test
-	void testExtraStringRecord_bug46213() {
-		FormulaRecord fr = new FormulaRecord();
-		fr.setValue(2.0);
-		StringRecord sr = new StringRecord();
-		sr.setString("NA");
-		SharedValueManager svm = SharedValueManager.createEmpty();
-		// bug 46213 -> String record was  supplied but formula record flag is not  set
-		FormulaRecordAggregate fra = new FormulaRecordAggregate(fr, sr, svm);
-		List<org.apache.poi.hssf.record.Record> vraRecs = new ArrayList<>();
-		fra.visitContainedRecords(vraRecs::add);
-		assertEquals(1, vraRecs.size());
-		assertEquals(fr, vraRecs.get(0));
-	}
-
-	@Test
-	void testArrayFormulas() {
-		int rownum = 4;
-		int colnum = 4;
-
-		FormulaRecord fr = new FormulaRecord();
-		fr.setRow(rownum);
-		fr.setColumn((short)colnum);
-
-		FormulaRecordAggregate agg = new FormulaRecordAggregate(fr, null, SharedValueManager.createEmpty());
-		Ptg[] ptgsForCell = {new ExpPtg(rownum, colnum)};
-		agg.setParsedExpression(ptgsForCell);
-
-		String formula = "SUM(A1:A3*B1:B3)";
-		Ptg[] ptgs = HSSFFormulaParser.parse(formula, null, FormulaType.ARRAY, 0);
-		agg.setArrayFormula(new CellRangeAddress(rownum, rownum, colnum, colnum), ptgs);
-
-		assertTrue(agg.isPartOfArrayFormula());
-		assertEquals("E5", agg.getArrayFormulaRange().formatAsString());
-		Ptg[] ptg = agg.getFormulaTokens();
-		String fmlaSer = FormulaRenderer.toFormulaString(null, ptg);
-		assertEquals(formula, fmlaSer);
+    @Test
+    void testBasic() {
+        FormulaRecord f = new FormulaRecord();
+        f.setCachedResultTypeString();
+        StringRecord s = new StringRecord();
+        s.setString("abc");
+        FormulaRecordAggregate fagg = new FormulaRecordAggregate(f, s, SharedValueManager.createEmpty());
+        assertEquals("abc", fagg.getStringValue());
+        assertFalse(fagg.isPartOfArrayFormula());
+    }
+
+    /**
+     * Sometimes a {@link StringRecord} appears after a {@link FormulaRecord} even though the
+     * formula has evaluated to a text value.  This might be more likely to occur when the formula
+     * <i>can</i> evaluate to a text value.<br>
+     * Bug 46213 attachment 22874 has such an extra {@link StringRecord} at stream offset 0x5765.
+     * This file seems to open in Excel (2007) with no trouble.  When it is re-saved, Excel omits
+     * the extra record.  POI should do the same.
+     */
+    @Test
+    void testExtraStringRecord_bug46213() {
+        FormulaRecord fr = new FormulaRecord();
+        fr.setValue(2.0);
+        StringRecord sr = new StringRecord();
+        sr.setString("NA");
+        SharedValueManager svm = SharedValueManager.createEmpty();
+        // bug 46213 -> String record was  supplied but formula record flag is not  set
+        FormulaRecordAggregate fra = new FormulaRecordAggregate(fr, sr, svm);
+        List<org.apache.poi.hssf.record.Record> vraRecs = new ArrayList<>();
+        fra.visitContainedRecords(vraRecs::add);
+        assertEquals(1, vraRecs.size());
+        assertEquals(fr, vraRecs.get(0));
+    }
+
+    @Test
+    void testArrayFormulas() {
+        int rownum = 4;
+        int colnum = 4;
+
+        FormulaRecord fr = new FormulaRecord();
+        fr.setRow(rownum);
+        fr.setColumn((short)colnum);
+
+        FormulaRecordAggregate agg = new FormulaRecordAggregate(fr, null, SharedValueManager.createEmpty());
+        Ptg[] ptgsForCell = {new ExpPtg(rownum, colnum)};
+        agg.setParsedExpression(ptgsForCell);
+
+        String formula = "SUM(A1:A3*B1:B3)";
+        Ptg[] ptgs = HSSFFormulaParser.parse(formula, null, FormulaType.ARRAY, 0);
+        agg.setArrayFormula(new CellRangeAddress(rownum, rownum, colnum, colnum), ptgs);
+
+        assertTrue(agg.isPartOfArrayFormula());
+        assertEquals("E5", agg.getArrayFormulaRange().formatAsString());
+        Ptg[] ptg = agg.getFormulaTokens();
+        String fmlaSer = FormulaRenderer.toFormulaString(null, ptg);
+        assertEquals(formula, fmlaSer);
 
         agg.removeArrayFormula(rownum, colnum);
         assertFalse(agg.isPartOfArrayFormula());

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java Sat May 22 20:56:44 2021
@@ -61,222 +61,222 @@ import org.junit.jupiter.api.Test;
  * Tess for {@link PageSettingsBlock}
  */
 final class TestPageSettingsBlock {
-	@Test
-	void testPrintSetup_bug46548() {
-		// PageSettingBlock in this file contains PLS (sid=x004D) record
-		// followed by ContinueRecord (sid=x003C)
-		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex46548-23133.xls");
-		HSSFSheet sheet = wb.getSheetAt(0);
-		HSSFPrintSetup ps = sheet.getPrintSetup();
-
-		// bug 46548: PageSettingBlock missing PrintSetupRecord record
-		assertEquals(1, ps.getCopies());
-	}
-
-	/**
-	 * Bug 46840 occurred because POI failed to recognise HEADERFOOTER as part of the
-	 * {@link PageSettingsBlock}.
-	 */
-	@Test
-	void testHeaderFooter_bug46840() {
-
-		int rowIx = 5;
-		int colIx = 6;
-		NumberRecord nr = new NumberRecord();
-		nr.setRow(rowIx);
-		nr.setColumn((short) colIx);
-		nr.setValue(3.0);
-
-		org.apache.poi.hssf.record.Record[] recs = {
-				BOFRecord.createSheetBOF(),
-				new HeaderRecord("&LSales Figures"),
-				new FooterRecord("&LJanuary"),
-				new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
-				new DimensionsRecord(),
-				new WindowTwoRecord(),
-				new UserSViewBegin(HexRead.readFromString("ED 77 3B 86 BC 3F 37 4C A9 58 60 23 43 68 54 4B 01 00 00 00 64 00 00 00 40 00 00 00 02 00 00 00 3D 80 04 00 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 3F FF FF 01 00")),
-				new HeaderRecord("&LSales Figures"),
-				new FooterRecord("&LJanuary"),
-				new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
-				new UserSViewEnd(HexRead.readFromString("01, 00")),
-
-				EOFRecord.instance,
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-		// bug 46480- two Page Settings Blocks found in the same sheet
-		InternalSheet sheet = InternalSheet.createSheet(rs);
-
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		sheet.visitContainedRecords(outRecs::add, rowIx);
-		assertEquals(13, outRecs.size());
-	}
-
-	/**
-	 * Bug 46953 occurred because POI didn't handle late PSB records properly.
-	 */
-	@Test
-	void testLateHeaderFooter_bug46953() {
-
-		int rowIx = 5;
-		int colIx = 6;
-		NumberRecord nr = new NumberRecord();
-		nr.setRow(rowIx);
-		nr.setColumn((short) colIx);
-		nr.setValue(3.0);
-
-		org.apache.poi.hssf.record.Record[] recs = {
-				BOFRecord.createSheetBOF(),
-				new HeaderRecord("&LSales Figures"),
-				new FooterRecord("&LJanuary"),
-				new DimensionsRecord(),
-				new WindowTwoRecord(),
-				new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
-				EOFRecord.instance,
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-		InternalSheet sheet = InternalSheet.createSheet(rs);
-
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		sheet.visitContainedRecords(outRecs::add, 0);
-		// Identified bug 46953 - EOF incorrectly appended to PSB
-		assertNotEquals(EOFRecord.instance, outRecs.get(4));
-		assertEquals(recs.length+1, outRecs.size()); // +1 for index record
-
-		Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
-		Class<?>[] exp = { BOFRecord.class, IndexRecord.class, HeaderRecord.class, FooterRecord.class,
-				HeaderFooterRecord.class, DimensionsRecord.class, WindowTwoRecord.class, EOFRecord.class };
-		assertArrayEquals(exp, act);
-	}
-	/**
-	 * Bug 47199 was due to the margin records being located well after the initial PSB records.
-	 * The example file supplied (attachment 23710) had three non-PSB record types
-	 * between the PRINTSETUP record and first MARGIN record:
-	 * <ul>
-	 * <li>PRINTSETUP(0x00A1)</li>
-	 * <li>DEFAULTCOLWIDTH(0x0055)</li>
-	 * <li>COLINFO(0x007D)</li>
-	 * <li>DIMENSIONS(0x0200)</li>
-	 * <li>BottomMargin(0x0029)</li>
-	 * </ul>
-	 */
-	@Test
-	void testLateMargins_bug47199() {
-
-		BottomMarginRecord bottomMargin = new BottomMarginRecord();
-		bottomMargin.setMargin(0.787F);
-
-		org.apache.poi.hssf.record.Record[] recs = {
-				BOFRecord.createSheetBOF(),
-				new HeaderRecord("&LSales Figures"),
-				new FooterRecord("&LJanuary"),
-				new DimensionsRecord(),
-				bottomMargin,
-				new WindowTwoRecord(),
-				EOFRecord.instance,
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-
-		// bug 47199a - failed to process late margins records
-		InternalSheet sheet = InternalSheet.createSheet(rs);
-
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		sheet.visitContainedRecords(outRecs::add, 0);
-		assertEquals(recs.length+1, outRecs.size()); // +1 for index record
-
-		Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
-		Class<?>[] exp = { BOFRecord.class, IndexRecord.class, HeaderRecord.class, FooterRecord.class,
-				BottomMarginRecord.class, DimensionsRecord.class, WindowTwoRecord.class, EOFRecord.class };
-		assertArrayEquals(exp, act);
-	}
-
-	/**
-	 * The PageSettingsBlock should not allow multiple copies of the same record.  This extra assertion
-	 * was added while fixing bug 47199.  All existing POI test samples comply with this requirement.
-	 */
-	@Test
-	void testDuplicatePSBRecord_bug47199() {
-		// Hypothetical setup of PSB records which should cause POI to crash
-		org.apache.poi.hssf.record.Record[] recs = {
-			new HeaderRecord("&LSales Figures"),
-			new HeaderRecord("&LInventory"),
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-
-		RecordFormatException ex = assertThrows(
-			RecordFormatException.class,
-			() -> new PageSettingsBlock(rs)
-		);
-		assertEquals("Duplicate PageSettingsBlock record (sid=0x14)", ex.getMessage());
-	}
-
-	/**
-	 * Excel tolerates missing header / footer records, but adds them (empty) in when re-saving.
-	 * This is not critical functionality but it has been decided to keep POI consistent with
-	 * Excel in this regard.
-	 */
-	@Test
-	void testMissingHeaderFooter() {
-		// initialise PSB with some records, but not the header / footer
-		org.apache.poi.hssf.record.Record[] recs = {
-				new HCenterRecord(),
-				new VCenterRecord(),
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-		PageSettingsBlock psb = new PageSettingsBlock(rs);
-
-		// serialize the PSB to see what records come out
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		psb.visitContainedRecords(outRecs::add);
-
-		assertNotEquals(2, outRecs.size(), "PageSettingsBlock didn't add missing header/footer records");
-
-		Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
-		Class<?>[] exp = { HeaderRecord.class, FooterRecord.class, HCenterRecord.class, VCenterRecord.class};
-		assertArrayEquals(exp, act);
-
-		// make sure the added header / footer records are empty
-		HeaderRecord hr = (HeaderRecord) outRecs.get(0);
-		assertEquals("", hr.getText());
-		FooterRecord fr = (FooterRecord) outRecs.get(1);
-		assertEquals("", fr.getText());
-	}
-
-	/**
-	 * Apparently it's OK to have more than one PLS record.
-	 * Attachment 23866 from bug 47415 had a PageSettingsBlock with two PLS records.  This file
-	 * seems to open OK in Excel(2007) but both PLS records are removed (perhaps because the
-	 * specified printers were not available on the testing machine).  Since the example file does
-	 * not upset Excel, POI will preserve multiple PLS records.</p>
-	 *
-	 * As of June 2009, PLS is still uninterpreted by POI
-	 */
-	@Test
-	void testDuplicatePLS_bug47415() {
-		Record plsA = new UnknownRecord(UnknownRecord.PLS_004D, HexRead.readFromString("BA AD F0 0D"));
-		Record plsB = new UnknownRecord(UnknownRecord.PLS_004D, HexRead.readFromString("DE AD BE EF"));
-		Record contB1 = new ContinueRecord(HexRead.readFromString("FE ED"));
-		Record contB2 = new ContinueRecord(HexRead.readFromString("FA CE"));
-		org.apache.poi.hssf.record.Record[] recs = {
-				new HeaderRecord("&LSales Figures"),
-				new FooterRecord("&LInventory"),
-				new HCenterRecord(),
-				new VCenterRecord(),
-				plsA,
-				plsB, contB1, contB2, // make sure continuing PLS is still OK
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
-		// bug 47415 - Duplicate PageSettingsBlock record (sid=0x4d)
-		PageSettingsBlock psb = new PageSettingsBlock(rs);
-
-		// serialize the PSB to see what records come out
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		psb.visitContainedRecords(outRecs::add);
-
-		// records were assembled in standard order, so this simple check is OK
-		assertArrayEquals(recs, outRecs.toArray(new Record[0]));
-	}
+    @Test
+    void testPrintSetup_bug46548() {
+        // PageSettingBlock in this file contains PLS (sid=x004D) record
+        // followed by ContinueRecord (sid=x003C)
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex46548-23133.xls");
+        HSSFSheet sheet = wb.getSheetAt(0);
+        HSSFPrintSetup ps = sheet.getPrintSetup();
 
-	@Test
+        // bug 46548: PageSettingBlock missing PrintSetupRecord record
+        assertEquals(1, ps.getCopies());
+    }
+
+    /**
+     * Bug 46840 occurred because POI failed to recognise HEADERFOOTER as part of the
+     * {@link PageSettingsBlock}.
+     */
+    @Test
+    void testHeaderFooter_bug46840() {
+
+        int rowIx = 5;
+        int colIx = 6;
+        NumberRecord nr = new NumberRecord();
+        nr.setRow(rowIx);
+        nr.setColumn((short) colIx);
+        nr.setValue(3.0);
+
+        org.apache.poi.hssf.record.Record[] recs = {
+                BOFRecord.createSheetBOF(),
+                new HeaderRecord("&LSales Figures"),
+                new FooterRecord("&LJanuary"),
+                new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
+                new DimensionsRecord(),
+                new WindowTwoRecord(),
+                new UserSViewBegin(HexRead.readFromString("ED 77 3B 86 BC 3F 37 4C A9 58 60 23 43 68 54 4B 01 00 00 00 64 00 00 00 40 00 00 00 02 00 00 00 3D 80 04 00 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 3F FF FF 01 00")),
+                new HeaderRecord("&LSales Figures"),
+                new FooterRecord("&LJanuary"),
+                new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
+                new UserSViewEnd(HexRead.readFromString("01, 00")),
+
+                EOFRecord.instance,
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+        // bug 46480- two Page Settings Blocks found in the same sheet
+        InternalSheet sheet = InternalSheet.createSheet(rs);
+
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        sheet.visitContainedRecords(outRecs::add, rowIx);
+        assertEquals(13, outRecs.size());
+    }
+
+    /**
+     * Bug 46953 occurred because POI didn't handle late PSB records properly.
+     */
+    @Test
+    void testLateHeaderFooter_bug46953() {
+
+        int rowIx = 5;
+        int colIx = 6;
+        NumberRecord nr = new NumberRecord();
+        nr.setRow(rowIx);
+        nr.setColumn((short) colIx);
+        nr.setValue(3.0);
+
+        org.apache.poi.hssf.record.Record[] recs = {
+                BOFRecord.createSheetBOF(),
+                new HeaderRecord("&LSales Figures"),
+                new FooterRecord("&LJanuary"),
+                new DimensionsRecord(),
+                new WindowTwoRecord(),
+                new HeaderFooterRecord(HexRead.readFromString("9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00")),
+                EOFRecord.instance,
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+        InternalSheet sheet = InternalSheet.createSheet(rs);
+
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        sheet.visitContainedRecords(outRecs::add, 0);
+        // Identified bug 46953 - EOF incorrectly appended to PSB
+        assertNotEquals(EOFRecord.instance, outRecs.get(4));
+        assertEquals(recs.length+1, outRecs.size()); // +1 for index record
+
+        Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
+        Class<?>[] exp = { BOFRecord.class, IndexRecord.class, HeaderRecord.class, FooterRecord.class,
+                HeaderFooterRecord.class, DimensionsRecord.class, WindowTwoRecord.class, EOFRecord.class };
+        assertArrayEquals(exp, act);
+    }
+    /**
+     * Bug 47199 was due to the margin records being located well after the initial PSB records.
+     * The example file supplied (attachment 23710) had three non-PSB record types
+     * between the PRINTSETUP record and first MARGIN record:
+     * <ul>
+     * <li>PRINTSETUP(0x00A1)</li>
+     * <li>DEFAULTCOLWIDTH(0x0055)</li>
+     * <li>COLINFO(0x007D)</li>
+     * <li>DIMENSIONS(0x0200)</li>
+     * <li>BottomMargin(0x0029)</li>
+     * </ul>
+     */
+    @Test
+    void testLateMargins_bug47199() {
+
+        BottomMarginRecord bottomMargin = new BottomMarginRecord();
+        bottomMargin.setMargin(0.787F);
+
+        org.apache.poi.hssf.record.Record[] recs = {
+                BOFRecord.createSheetBOF(),
+                new HeaderRecord("&LSales Figures"),
+                new FooterRecord("&LJanuary"),
+                new DimensionsRecord(),
+                bottomMargin,
+                new WindowTwoRecord(),
+                EOFRecord.instance,
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+
+        // bug 47199a - failed to process late margins records
+        InternalSheet sheet = InternalSheet.createSheet(rs);
+
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        sheet.visitContainedRecords(outRecs::add, 0);
+        assertEquals(recs.length+1, outRecs.size()); // +1 for index record
+
+        Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
+        Class<?>[] exp = { BOFRecord.class, IndexRecord.class, HeaderRecord.class, FooterRecord.class,
+                BottomMarginRecord.class, DimensionsRecord.class, WindowTwoRecord.class, EOFRecord.class };
+        assertArrayEquals(exp, act);
+    }
+
+    /**
+     * The PageSettingsBlock should not allow multiple copies of the same record.  This extra assertion
+     * was added while fixing bug 47199.  All existing POI test samples comply with this requirement.
+     */
+    @Test
+    void testDuplicatePSBRecord_bug47199() {
+        // Hypothetical setup of PSB records which should cause POI to crash
+        org.apache.poi.hssf.record.Record[] recs = {
+            new HeaderRecord("&LSales Figures"),
+            new HeaderRecord("&LInventory"),
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+
+        RecordFormatException ex = assertThrows(
+            RecordFormatException.class,
+            () -> new PageSettingsBlock(rs)
+        );
+        assertEquals("Duplicate PageSettingsBlock record (sid=0x14)", ex.getMessage());
+    }
+
+    /**
+     * Excel tolerates missing header / footer records, but adds them (empty) in when re-saving.
+     * This is not critical functionality but it has been decided to keep POI consistent with
+     * Excel in this regard.
+     */
+    @Test
+    void testMissingHeaderFooter() {
+        // initialise PSB with some records, but not the header / footer
+        org.apache.poi.hssf.record.Record[] recs = {
+                new HCenterRecord(),
+                new VCenterRecord(),
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+        PageSettingsBlock psb = new PageSettingsBlock(rs);
+
+        // serialize the PSB to see what records come out
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        psb.visitContainedRecords(outRecs::add);
+
+        assertNotEquals(2, outRecs.size(), "PageSettingsBlock didn't add missing header/footer records");
+
+        Class<?>[] act = outRecs.stream().map(Object::getClass).toArray(Class[]::new);
+        Class<?>[] exp = { HeaderRecord.class, FooterRecord.class, HCenterRecord.class, VCenterRecord.class};
+        assertArrayEquals(exp, act);
+
+        // make sure the added header / footer records are empty
+        HeaderRecord hr = (HeaderRecord) outRecs.get(0);
+        assertEquals("", hr.getText());
+        FooterRecord fr = (FooterRecord) outRecs.get(1);
+        assertEquals("", fr.getText());
+    }
+
+    /**
+     * Apparently it's OK to have more than one PLS record.
+     * Attachment 23866 from bug 47415 had a PageSettingsBlock with two PLS records.  This file
+     * seems to open OK in Excel(2007) but both PLS records are removed (perhaps because the
+     * specified printers were not available on the testing machine).  Since the example file does
+     * not upset Excel, POI will preserve multiple PLS records.</p>
+     *
+     * As of June 2009, PLS is still uninterpreted by POI
+     */
+    @Test
+    void testDuplicatePLS_bug47415() {
+        Record plsA = new UnknownRecord(UnknownRecord.PLS_004D, HexRead.readFromString("BA AD F0 0D"));
+        Record plsB = new UnknownRecord(UnknownRecord.PLS_004D, HexRead.readFromString("DE AD BE EF"));
+        Record contB1 = new ContinueRecord(HexRead.readFromString("FE ED"));
+        Record contB2 = new ContinueRecord(HexRead.readFromString("FA CE"));
+        org.apache.poi.hssf.record.Record[] recs = {
+                new HeaderRecord("&LSales Figures"),
+                new FooterRecord("&LInventory"),
+                new HCenterRecord(),
+                new VCenterRecord(),
+                plsA,
+                plsB, contB1, contB2, // make sure continuing PLS is still OK
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+        // bug 47415 - Duplicate PageSettingsBlock record (sid=0x4d)
+        PageSettingsBlock psb = new PageSettingsBlock(rs);
+
+        // serialize the PSB to see what records come out
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        psb.visitContainedRecords(outRecs::add);
+
+        // records were assembled in standard order, so this simple check is OK
+        assertArrayEquals(recs, outRecs.toArray(new Record[0]));
+    }
+
+    @Test
     void testDuplicateHeaderFooter_bug48026() {
 
         org.apache.poi.hssf.record.Record[] recs = {
@@ -332,9 +332,9 @@ final class TestPageSettingsBlock {
         };
 
         assertArrayEquals(
-			Stream.of(expectedRecs).map(Object::getClass).toArray(Class[]::new),
-			outRecs.stream().map(Object::getClass).toArray(Class[]::new)
-		);
+            Stream.of(expectedRecs).map(Object::getClass).toArray(Class[]::new),
+            outRecs.stream().map(Object::getClass).toArray(Class[]::new)
+        );
 
         HeaderFooterRecord hd1 = (HeaderFooterRecord)expectedRecs[4];
         //GUID is zero
@@ -348,7 +348,7 @@ final class TestPageSettingsBlock {
         assertArrayEquals(svb.getGuid(), hd2.getGuid());
     }
 
-	@Test
+    @Test
     void testDuplicateHeaderFooterInside_bug48026() {
 
         Record[] recs = {
@@ -379,7 +379,7 @@ final class TestPageSettingsBlock {
         // Bug 48026 : Duplicate PageSettingsBlock record (sid=0x89c)
         InternalSheet sheet = InternalSheet.createSheet(rs);
 
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
         sheet.visitContainedRecords(outRecs::add, 0);
 
         assertEquals(recs.length+1, outRecs.size());
@@ -406,10 +406,10 @@ final class TestPageSettingsBlock {
                 recs[11],  //EOFRecord
         };
 
-		assertArrayEquals(
-			Stream.of(expectedRecs).map(Object::getClass).toArray(Class[]::new),
-			outRecs.stream().map(Object::getClass).toArray(Class[]::new)
-		);
+        assertArrayEquals(
+            Stream.of(expectedRecs).map(Object::getClass).toArray(Class[]::new),
+            outRecs.stream().map(Object::getClass).toArray(Class[]::new)
+        );
 
         HeaderFooterRecord hd1 = (HeaderFooterRecord)expectedRecs[10];
         //GUID is zero

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestRowRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestRowRecordsAggregate.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestRowRecordsAggregate.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestRowRecordsAggregate.java Sat May 22 20:56:44 2021
@@ -50,110 +50,110 @@ import org.junit.jupiter.api.Test;
 final class TestRowRecordsAggregate {
 
     @Test
-	void testRowGet() {
-		RowRecordsAggregate rra = new RowRecordsAggregate();
-		RowRecord rr = new RowRecord(4);
-		rra.insertRow(rr);
-		rra.insertRow(new RowRecord(1));
+    void testRowGet() {
+        RowRecordsAggregate rra = new RowRecordsAggregate();
+        RowRecord rr = new RowRecord(4);
+        rra.insertRow(rr);
+        rra.insertRow(new RowRecord(1));
 
-		RowRecord rr1 = rra.getRow(4);
+        RowRecord rr1 = rra.getRow(4);
 
-		assertNotNull(rr1);
-		assertEquals(4, rr1.getRowNumber(), "Row number is 1");
+        assertNotNull(rr1);
+        assertEquals(4, rr1.getRowNumber(), "Row number is 1");
         assertSame(rr1, rr, "Row record retrieved is identical ");
-	}
+    }
 
-	/**
-	 * Prior to Aug 2008, POI would re-serialize spreadsheets with {@link ArrayRecord}s or
-	 * {@link TableRecord}s with those records out of order.  Similar to
-	 * {@link SharedFormulaRecord}s, these records should appear immediately after the first
-	 * {@link FormulaRecord}s that they apply to (and only once).<br>
-	 */
+    /**
+     * Prior to Aug 2008, POI would re-serialize spreadsheets with {@link ArrayRecord}s or
+     * {@link TableRecord}s with those records out of order.  Similar to
+     * {@link SharedFormulaRecord}s, these records should appear immediately after the first
+     * {@link FormulaRecord}s that they apply to (and only once).<br>
+     */
     @Test
-	void testArraysAndTables() throws Exception {
-		try (HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testArraysAndTables.xls")) {
-			final List<org.apache.poi.hssf.record.Record> sheetRecs = new ArrayList<>();
-			wb.getSheetAt(0).getSheet().visitContainedRecords(sheetRecs::add, 0);
-
-			int countArrayFormulas = verifySharedValues(sheetRecs, ArrayRecord.class);
-			assertEquals(5, countArrayFormulas);
-			int countTableFormulas = verifySharedValues(sheetRecs, TableRecord.class);
-			assertEquals(3, countTableFormulas);
-
-			// Note - SharedFormulaRecords are currently not re-serialized by POI (each is extracted
-			// into many non-shared formulas), but if they ever were, the same rules would apply.
-			int countSharedFormulas = verifySharedValues(sheetRecs, SharedFormulaRecord.class);
-			assertEquals(0, countSharedFormulas);
-
-
-//		if (false) { // set true to observe re-serialized file
-//			File f = new File(System.getProperty("java.io.tmpdir") + "/testArraysAndTables-out.xls");
-//			try {
-//				OutputStream os = new FileOutputStream(f);
-//				wb.write(os);
-//				os.close();
-//			} catch (IOException e) {
-//				throw new RuntimeException(e);
-//			}
-//			System.out.println("Output file to " + f.getAbsolutePath());
-//		}
-
-		}
-	}
-
-	private static int verifySharedValues(List<org.apache.poi.hssf.record.Record> recs, Class<? extends SharedValueRecordBase> shfClass) {
-
-		int result =0;
-		for(int i=0; i<recs.size(); i++) {
-			Record rec = recs.get(i);
-			if (rec.getClass() == shfClass) {
-				result++;
-				Record prevRec = recs.get(i-1);
-				assertTrue(prevRec instanceof FormulaRecord,
-					"Bad record order at index " + i + ": Formula record expected but got (" + prevRec.getClass().getName() + ")");
-				verifySharedFormula((FormulaRecord) prevRec, rec);
-			}
-		}
-		return result;
-	}
-
-	private static void verifySharedFormula(FormulaRecord firstFormula, Record rec) {
-		CellRangeAddress8Bit range = ((SharedValueRecordBase)rec).getRange();
-		assertEquals(range.getFirstRow(), firstFormula.getRow());
-		assertEquals(range.getFirstColumn(), firstFormula.getColumn());
-	}
-
-	/**
-	 * This problem was noted as the overt symptom of bug 46280.  The logic for skipping {@link
-	 * UnknownRecord}s in the constructor {@link RowRecordsAggregate} did not allow for the
-	 * possibility of tailing {@link ContinueRecord}s.<br>
-	 * The functionality change being tested here is actually not critical to the overall fix
-	 * for bug 46280, since the fix involved making sure the that offending <i>PivotTable</i>
-	 * records do not get into {@link RowRecordsAggregate}.<br>
-	 * This fix in {@link RowRecordsAggregate} was implemented anyway since any {@link
-	 * UnknownRecord} has the potential of being 'continued'.
-	 */
-	@Test
-	void testUnknownContinue_bug46280() {
-		org.apache.poi.hssf.record.Record[] inRecs = {
-			new RowRecord(0),
-			new NumberRecord(),
-			new UnknownRecord(0x5555, "dummydata".getBytes(LocaleUtil.CHARSET_1252)),
-			new ContinueRecord("moredummydata".getBytes(LocaleUtil.CHARSET_1252)),
-		};
-		RecordStream rs = new RecordStream(Arrays.asList(inRecs), 0);
-		RowRecordsAggregate rra;
-		try {
-			rra = new RowRecordsAggregate(rs, SharedValueManager.createEmpty());
-		} catch (RuntimeException e) {
-			if (e.getMessage().startsWith("Unexpected record type")) {
-				fail("Identified bug 46280a");
-			}
-			throw e;
-		}
-
-		List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
-		rra.visitContainedRecords(outRecs::add);
-		assertEquals(5, outRecs.size());
-	}
+    void testArraysAndTables() throws Exception {
+        try (HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testArraysAndTables.xls")) {
+            final List<org.apache.poi.hssf.record.Record> sheetRecs = new ArrayList<>();
+            wb.getSheetAt(0).getSheet().visitContainedRecords(sheetRecs::add, 0);
+
+            int countArrayFormulas = verifySharedValues(sheetRecs, ArrayRecord.class);
+            assertEquals(5, countArrayFormulas);
+            int countTableFormulas = verifySharedValues(sheetRecs, TableRecord.class);
+            assertEquals(3, countTableFormulas);
+
+            // Note - SharedFormulaRecords are currently not re-serialized by POI (each is extracted
+            // into many non-shared formulas), but if they ever were, the same rules would apply.
+            int countSharedFormulas = verifySharedValues(sheetRecs, SharedFormulaRecord.class);
+            assertEquals(0, countSharedFormulas);
+
+
+//      if (false) { // set true to observe re-serialized file
+//          File f = new File(System.getProperty("java.io.tmpdir") + "/testArraysAndTables-out.xls");
+//          try {
+//              OutputStream os = new FileOutputStream(f);
+//              wb.write(os);
+//              os.close();
+//          } catch (IOException e) {
+//              throw new RuntimeException(e);
+//          }
+//          System.out.println("Output file to " + f.getAbsolutePath());
+//      }
+
+        }
+    }
+
+    private static int verifySharedValues(List<org.apache.poi.hssf.record.Record> recs, Class<? extends SharedValueRecordBase> shfClass) {
+
+        int result =0;
+        for(int i=0; i<recs.size(); i++) {
+            Record rec = recs.get(i);
+            if (rec.getClass() == shfClass) {
+                result++;
+                Record prevRec = recs.get(i-1);
+                assertTrue(prevRec instanceof FormulaRecord,
+                    "Bad record order at index " + i + ": Formula record expected but got (" + prevRec.getClass().getName() + ")");
+                verifySharedFormula((FormulaRecord) prevRec, rec);
+            }
+        }
+        return result;
+    }
+
+    private static void verifySharedFormula(FormulaRecord firstFormula, Record rec) {
+        CellRangeAddress8Bit range = ((SharedValueRecordBase)rec).getRange();
+        assertEquals(range.getFirstRow(), firstFormula.getRow());
+        assertEquals(range.getFirstColumn(), firstFormula.getColumn());
+    }
+
+    /**
+     * This problem was noted as the overt symptom of bug 46280.  The logic for skipping {@link
+     * UnknownRecord}s in the constructor {@link RowRecordsAggregate} did not allow for the
+     * possibility of tailing {@link ContinueRecord}s.<br>
+     * The functionality change being tested here is actually not critical to the overall fix
+     * for bug 46280, since the fix involved making sure the that offending <i>PivotTable</i>
+     * records do not get into {@link RowRecordsAggregate}.<br>
+     * This fix in {@link RowRecordsAggregate} was implemented anyway since any {@link
+     * UnknownRecord} has the potential of being 'continued'.
+     */
+    @Test
+    void testUnknownContinue_bug46280() {
+        org.apache.poi.hssf.record.Record[] inRecs = {
+            new RowRecord(0),
+            new NumberRecord(),
+            new UnknownRecord(0x5555, "dummydata".getBytes(LocaleUtil.CHARSET_1252)),
+            new ContinueRecord("moredummydata".getBytes(LocaleUtil.CHARSET_1252)),
+        };
+        RecordStream rs = new RecordStream(Arrays.asList(inRecs), 0);
+        RowRecordsAggregate rra;
+        try {
+            rra = new RowRecordsAggregate(rs, SharedValueManager.createEmpty());
+        } catch (RuntimeException e) {
+            if (e.getMessage().startsWith("Unexpected record type")) {
+                fail("Identified bug 46280a");
+            }
+            throw e;
+        }
+
+        List<org.apache.poi.hssf.record.Record> outRecs = new ArrayList<>();
+        rra.visitContainedRecords(outRecs::add);
+        assertEquals(5, outRecs.size());
+    }
 }

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestSharedValueManager.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestSharedValueManager.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestSharedValueManager.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestSharedValueManager.java Sat May 22 20:56:44 2021
@@ -35,112 +35,112 @@ import org.junit.jupiter.api.Test;
  */
 final class TestSharedValueManager {
 
-	/**
-	 * This Excel workbook contains two sheets that each have a pair of overlapping shared formula
-	 * ranges.  The first sheet has one row and one column shared formula ranges which intersect.
-	 * The second sheet has two column shared formula ranges - one contained within the other.
-	 * These shared formula ranges were created by fill-dragging a single cell formula across the
-	 * desired region.  The larger shared formula ranges were placed first.<br>
-	 *
-	 * There are probably many ways to produce similar effects, but it should be noted that Excel
-	 * is quite temperamental in this regard.  Slight variations in technique can cause the shared
-	 * formulas to spill out into plain formula records (which would make these tests pointless).
-	 *
-	 */
-	private static final String SAMPLE_FILE_NAME = "overlapSharedFormula.xls";
-	/**
-	 * Some of these bugs are intermittent, and the test author couldn't think of a way to write
-	 * test code to hit them bug deterministically. The reason for the unpredictability is that
-	 * the bugs depended on the {@link SharedFormulaRecord}s being searched in a particular order.
-	 * At the time of writing of the test, the order was being determined by the call to {@link
-	 * Collection#toArray(Object[])} on {@link HashMap#values()} where the items in the map were
-	 * using default {@link Object#hashCode()}<br>
-	 */
-	private static final int MAX_ATTEMPTS=5;
-
-	/**
-	 * This bug happened when there were two or more shared formula ranges that overlapped.  POI
-	 * would sometimes associate formulas in the overlapping region with the wrong shared formula
-	 */
-	@Test
-	void testPartiallyOverlappingRanges() {
-
-
-		for (int attempt=1; attempt < MAX_ATTEMPTS; attempt++) {
-			HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_FILE_NAME);
-
-			HSSFSheet sheet = wb.getSheetAt(0);
-			assertEquals("1+1", sheet.getRow(2).getCell(0).getCellFormula());
-			String act = sheet.getRow(3).getCell(0).getCellFormula();
-			assertNotEquals("wrong shared formula record chosen", "1+1", act);
-			act = sheet.getRow(3).getCell(0).getCellFormula();
-			assertEquals("2+2", act);
-
-			int[] count = { 0 };
-			sheet.getSheet().visitContainedRecords(r -> count[0] += r instanceof SharedFormulaRecord ? 1 : 0, 0);
-			assertEquals(2, count[0]);
-		}
-	}
-
-	/**
-	 * This bug occurs for similar reasons to the bug in {@link #testPartiallyOverlappingRanges()}
-	 * but the symptoms are much uglier - serialization fails with {@link NullPointerException}.<br>
-	 */
-	@Test
-	void testCompletelyOverlappedRanges() {
-		for (int attempt=1; attempt < MAX_ATTEMPTS; attempt++) {
-			HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_FILE_NAME);
-
-			HSSFSheet sheet = wb.getSheetAt(1);
-
-			int[] count = { 0 };
-
-			// NullPointerException -> cannot reserialize completely overlapped shared formula
-			sheet.getSheet().visitContainedRecords(r -> count[0] += r instanceof SharedFormulaRecord ? 1 : 0, 0);
-			assertEquals(2, count[0]);
-		}
-	}
-
-	/**
-	 * Tests fix for a bug in the way shared formula cells are associated with shared formula
-	 * records.  Prior to this fix, POI would attempt to use the upper left corner of the
-	 * shared formula range as the locator cell.  The correct cell to use is the 'first cell'
-	 * in the shared formula group which is not always the top left cell.  This is possible
-	 * because shared formula groups may be sparse and may overlap.<br>
-	 *
-	 * Two existing sample files (15228.xls and ex45046-21984.xls) had similar issues.
-	 * These were not explored fully, but seem to be fixed now.
-	 */
-	@Test
-	void testRecalculateFormulas47747() {
-
-		/*
-		 * ex47747-sharedFormula.xls is a heavily cut-down version of the spreadsheet from
-		 * the attachment (id=24176) in Bugzilla 47747.  This was done to make the sample
-		 * file smaller, which hopefully allows the special data encoding condition to be
-		 * seen more easily.  Care must be taken when modifying this file since the
-		 * special conditions are easily destroyed (which would make this test useless).
-		 * It seems that removing the worksheet protection has made this more so - if the
-		 * current file is re-saved in Excel(2007) the bug condition disappears.
-		 *
-		 *
-		 * Using BiffViewer, one can see that there are two shared formula groups representing
-		 * the essentially same formula over ~20 cells.  The shared group ranges overlap and
-		 * are A12:Q20 and A20:Q27.  The locator cell ('first cell') for the second group is
-		 * Q20 which is not the top left cell of the enclosing range.  It is this specific
-		 * condition which caused the bug to occur
-		 */
-		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex47747-sharedFormula.xls");
-
-		// pick out a cell from within the second shared formula group
-		HSSFCell cell = wb.getSheetAt(0).getRow(23).getCell(0);
-		// bug occurs if the formula record has been associated
-		// with the first (and not the second) shared formula group
-		String formulaText = cell.getCellFormula();
-		assertEquals("$AF24*A$7", formulaText);
-	}
+    /**
+     * This Excel workbook contains two sheets that each have a pair of overlapping shared formula
+     * ranges.  The first sheet has one row and one column shared formula ranges which intersect.
+     * The second sheet has two column shared formula ranges - one contained within the other.
+     * These shared formula ranges were created by fill-dragging a single cell formula across the
+     * desired region.  The larger shared formula ranges were placed first.<br>
+     *
+     * There are probably many ways to produce similar effects, but it should be noted that Excel
+     * is quite temperamental in this regard.  Slight variations in technique can cause the shared
+     * formulas to spill out into plain formula records (which would make these tests pointless).
+     *
+     */
+    private static final String SAMPLE_FILE_NAME = "overlapSharedFormula.xls";
+    /**
+     * Some of these bugs are intermittent, and the test author couldn't think of a way to write
+     * test code to hit them bug deterministically. The reason for the unpredictability is that
+     * the bugs depended on the {@link SharedFormulaRecord}s being searched in a particular order.
+     * At the time of writing of the test, the order was being determined by the call to {@link
+     * Collection#toArray(Object[])} on {@link HashMap#values()} where the items in the map were
+     * using default {@link Object#hashCode()}<br>
+     */
+    private static final int MAX_ATTEMPTS=5;
+
+    /**
+     * This bug happened when there were two or more shared formula ranges that overlapped.  POI
+     * would sometimes associate formulas in the overlapping region with the wrong shared formula
+     */
+    @Test
+    void testPartiallyOverlappingRanges() {
+
+
+        for (int attempt=1; attempt < MAX_ATTEMPTS; attempt++) {
+            HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_FILE_NAME);
+
+            HSSFSheet sheet = wb.getSheetAt(0);
+            assertEquals("1+1", sheet.getRow(2).getCell(0).getCellFormula());
+            String act = sheet.getRow(3).getCell(0).getCellFormula();
+            assertNotEquals("wrong shared formula record chosen", "1+1", act);
+            act = sheet.getRow(3).getCell(0).getCellFormula();
+            assertEquals("2+2", act);
+
+            int[] count = { 0 };
+            sheet.getSheet().visitContainedRecords(r -> count[0] += r instanceof SharedFormulaRecord ? 1 : 0, 0);
+            assertEquals(2, count[0]);
+        }
+    }
+
+    /**
+     * This bug occurs for similar reasons to the bug in {@link #testPartiallyOverlappingRanges()}
+     * but the symptoms are much uglier - serialization fails with {@link NullPointerException}.<br>
+     */
+    @Test
+    void testCompletelyOverlappedRanges() {
+        for (int attempt=1; attempt < MAX_ATTEMPTS; attempt++) {
+            HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_FILE_NAME);
+
+            HSSFSheet sheet = wb.getSheetAt(1);
+
+            int[] count = { 0 };
+
+            // NullPointerException -> cannot reserialize completely overlapped shared formula
+            sheet.getSheet().visitContainedRecords(r -> count[0] += r instanceof SharedFormulaRecord ? 1 : 0, 0);
+            assertEquals(2, count[0]);
+        }
+    }
+
+    /**
+     * Tests fix for a bug in the way shared formula cells are associated with shared formula
+     * records.  Prior to this fix, POI would attempt to use the upper left corner of the
+     * shared formula range as the locator cell.  The correct cell to use is the 'first cell'
+     * in the shared formula group which is not always the top left cell.  This is possible
+     * because shared formula groups may be sparse and may overlap.<br>
+     *
+     * Two existing sample files (15228.xls and ex45046-21984.xls) had similar issues.
+     * These were not explored fully, but seem to be fixed now.
+     */
+    @Test
+    void testRecalculateFormulas47747() {
+
+        /*
+         * ex47747-sharedFormula.xls is a heavily cut-down version of the spreadsheet from
+         * the attachment (id=24176) in Bugzilla 47747.  This was done to make the sample
+         * file smaller, which hopefully allows the special data encoding condition to be
+         * seen more easily.  Care must be taken when modifying this file since the
+         * special conditions are easily destroyed (which would make this test useless).
+         * It seems that removing the worksheet protection has made this more so - if the
+         * current file is re-saved in Excel(2007) the bug condition disappears.
+         *
+         *
+         * Using BiffViewer, one can see that there are two shared formula groups representing
+         * the essentially same formula over ~20 cells.  The shared group ranges overlap and
+         * are A12:Q20 and A20:Q27.  The locator cell ('first cell') for the second group is
+         * Q20 which is not the top left cell of the enclosing range.  It is this specific
+         * condition which caused the bug to occur
+         */
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex47747-sharedFormula.xls");
+
+        // pick out a cell from within the second shared formula group
+        HSSFCell cell = wb.getSheetAt(0).getRow(23).getCell(0);
+        // bug occurs if the formula record has been associated
+        // with the first (and not the second) shared formula group
+        String formulaText = cell.getCellFormula();
+        assertEquals("$AF24*A$7", formulaText);
+    }
 
-	@Test
+    @Test
     void testBug52527() {
         HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("52527.xls");
         HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);

Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java Sat May 22 20:56:44 2021
@@ -52,360 +52,360 @@ import org.junit.jupiter.api.Test;
  * Tests for {@link ValueRecordsAggregate}
  */
 final class TestValueRecordsAggregate {
-	private static final String ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE = "AbnormalSharedFormulaFlag.xls";
-	private final ValueRecordsAggregate valueRecord = new ValueRecordsAggregate();
+    private static final String ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE = "AbnormalSharedFormulaFlag.xls";
+    private final ValueRecordsAggregate valueRecord = new ValueRecordsAggregate();
 
-	private List<CellValueRecordInterface> getValueRecords() {
-	    List<CellValueRecordInterface> list = new ArrayList<>();
-	    for ( CellValueRecordInterface rec : valueRecord ) {
-	        list.add(rec);
-	    }
-	    return Collections.unmodifiableList(list);
-	}
-
-	/**
-	 * Make sure the shared formula DOESNT makes it to the FormulaRecordAggregate when being parsed
-	 * as part of the value records
-	 */
+    private List<CellValueRecordInterface> getValueRecords() {
+        List<CellValueRecordInterface> list = new ArrayList<>();
+        for ( CellValueRecordInterface rec : valueRecord ) {
+            list.add(rec);
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    /**
+     * Make sure the shared formula DOESNT makes it to the FormulaRecordAggregate when being parsed
+     * as part of the value records
+     */
     @Test
-	void testSharedFormula() {
-		List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
-		records.add(new FormulaRecord());
-		records.add(new SharedFormulaRecord());
-		records.add(new WindowTwoRecord());
-
-		constructValueRecord(records);
-		List<CellValueRecordInterface> cvrs = getValueRecords();
-		//Ensure that the SharedFormulaRecord has been converted
-		assertEquals(1, cvrs.size());
-
-		CellValueRecordInterface record = cvrs.get(0);
-		assertNotNull( record, "Row contains a value" );
-		assertTrue( ( record instanceof FormulaRecordAggregate ), "First record is a FormulaRecordsAggregate");
-	}
-
-	private void constructValueRecord(List<org.apache.poi.hssf.record.Record> records) {
-		RowBlocksReader rbr = new RowBlocksReader(new RecordStream(records, 0));
-		SharedValueManager sfrh = rbr.getSharedFormulaManager();
-		RecordStream rs = rbr.getPlainRecordStream();
-		while(rs.hasNext()) {
-			Record rec = rs.getNext();
-			valueRecord.construct((CellValueRecordInterface)rec, rs, sfrh);
-		}
-	}
-
-	private static List<org.apache.poi.hssf.record.Record> testData() {
-		List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
-		FormulaRecord formulaRecord = new FormulaRecord();
-		BlankRecord blankRecord = new BlankRecord();
-		formulaRecord.setRow(1);
-		formulaRecord.setColumn((short) 1);
-		blankRecord.setRow(2);
-		blankRecord.setColumn((short) 2);
-		records.add(formulaRecord);
-		records.add(blankRecord);
-		records.add(new WindowTwoRecord());
-		return records;
-	}
+    void testSharedFormula() {
+        List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
+        records.add(new FormulaRecord());
+        records.add(new SharedFormulaRecord());
+        records.add(new WindowTwoRecord());
+
+        constructValueRecord(records);
+        List<CellValueRecordInterface> cvrs = getValueRecords();
+        //Ensure that the SharedFormulaRecord has been converted
+        assertEquals(1, cvrs.size());
+
+        CellValueRecordInterface record = cvrs.get(0);
+        assertNotNull( record, "Row contains a value" );
+        assertTrue( ( record instanceof FormulaRecordAggregate ), "First record is a FormulaRecordsAggregate");
+    }
+
+    private void constructValueRecord(List<org.apache.poi.hssf.record.Record> records) {
+        RowBlocksReader rbr = new RowBlocksReader(new RecordStream(records, 0));
+        SharedValueManager sfrh = rbr.getSharedFormulaManager();
+        RecordStream rs = rbr.getPlainRecordStream();
+        while(rs.hasNext()) {
+            Record rec = rs.getNext();
+            valueRecord.construct((CellValueRecordInterface)rec, rs, sfrh);
+        }
+    }
+
+    private static List<org.apache.poi.hssf.record.Record> testData() {
+        List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
+        FormulaRecord formulaRecord = new FormulaRecord();
+        BlankRecord blankRecord = new BlankRecord();
+        formulaRecord.setRow(1);
+        formulaRecord.setColumn((short) 1);
+        blankRecord.setRow(2);
+        blankRecord.setColumn((short) 2);
+        records.add(formulaRecord);
+        records.add(blankRecord);
+        records.add(new WindowTwoRecord());
+        return records;
+    }
 
     @Test
-	void testInsertCell() {
-		assertEquals(0, getValueRecords().size());
+    void testInsertCell() {
+        assertEquals(0, getValueRecords().size());
 
-		BlankRecord blankRecord = newBlankRecord();
-		valueRecord.insertCell( blankRecord );
-		assertEquals(1, getValueRecords().size());
-	}
+        BlankRecord blankRecord = newBlankRecord();
+        valueRecord.insertCell( blankRecord );
+        assertEquals(1, getValueRecords().size());
+    }
 
     @Test
     void testRemoveCell() {
-		BlankRecord blankRecord1 = newBlankRecord();
-		valueRecord.insertCell( blankRecord1 );
-		BlankRecord blankRecord2 = newBlankRecord();
-		valueRecord.removeCell( blankRecord2 );
-		assertEquals(0, getValueRecords().size());
-
-		// removing an already empty cell just falls through
-		valueRecord.removeCell( blankRecord2 );
-	}
+        BlankRecord blankRecord1 = newBlankRecord();
+        valueRecord.insertCell( blankRecord1 );
+        BlankRecord blankRecord2 = newBlankRecord();
+        valueRecord.removeCell( blankRecord2 );
+        assertEquals(0, getValueRecords().size());
+
+        // removing an already empty cell just falls through
+        valueRecord.removeCell( blankRecord2 );
+    }
 
     @Test
-	void testGetPhysicalNumberOfCells() {
-		assertEquals(0, valueRecord.getPhysicalNumberOfCells());
-		BlankRecord blankRecord1 = newBlankRecord();
-		valueRecord.insertCell( blankRecord1 );
-		assertEquals(1, valueRecord.getPhysicalNumberOfCells());
-		valueRecord.removeCell( blankRecord1 );
-		assertEquals(0, valueRecord.getPhysicalNumberOfCells());
-	}
+    void testGetPhysicalNumberOfCells() {
+        assertEquals(0, valueRecord.getPhysicalNumberOfCells());
+        BlankRecord blankRecord1 = newBlankRecord();
+        valueRecord.insertCell( blankRecord1 );
+        assertEquals(1, valueRecord.getPhysicalNumberOfCells());
+        valueRecord.removeCell( blankRecord1 );
+        assertEquals(0, valueRecord.getPhysicalNumberOfCells());
+    }
 
     @Test
-	void testGetFirstCellNum() {
-		assertEquals( -1, valueRecord.getFirstCellNum() );
-		valueRecord.insertCell( newBlankRecord( 2, 2 ) );
-		assertEquals( 2, valueRecord.getFirstCellNum() );
-		valueRecord.insertCell( newBlankRecord( 3, 3 ) );
-		assertEquals( 2, valueRecord.getFirstCellNum() );
-
-		// Note: Removal doesn't currently reset the first column.  It probably should but it doesn't.
-		valueRecord.removeCell( newBlankRecord( 2, 2 ) );
-		assertEquals( 2, valueRecord.getFirstCellNum() );
-	}
+    void testGetFirstCellNum() {
+        assertEquals( -1, valueRecord.getFirstCellNum() );
+        valueRecord.insertCell( newBlankRecord( 2, 2 ) );
+        assertEquals( 2, valueRecord.getFirstCellNum() );
+        valueRecord.insertCell( newBlankRecord( 3, 3 ) );
+        assertEquals( 2, valueRecord.getFirstCellNum() );
+
+        // Note: Removal doesn't currently reset the first column.  It probably should but it doesn't.
+        valueRecord.removeCell( newBlankRecord( 2, 2 ) );
+        assertEquals( 2, valueRecord.getFirstCellNum() );
+    }
 
     @Test
-	void testGetLastCellNum() {
-		assertEquals( -1, valueRecord.getLastCellNum() );
-		valueRecord.insertCell( newBlankRecord( 2, 2 ) );
-		assertEquals( 2, valueRecord.getLastCellNum() );
-		valueRecord.insertCell( newBlankRecord( 3, 3 ) );
-		assertEquals( 3, valueRecord.getLastCellNum() );
-
-		// Note: Removal doesn't currently reset the last column.  It probably should but it doesn't.
-		valueRecord.removeCell( newBlankRecord( 3, 3 ) );
-		assertEquals( 3, valueRecord.getLastCellNum() );
-
-	}
-
-
-	private static final class SerializerVisitor implements RecordVisitor {
-		private final byte[] _buf;
-		private int _writeIndex;
-		public SerializerVisitor(byte[] buf) {
-			_buf = buf;
-			_writeIndex = 0;
+    void testGetLastCellNum() {
+        assertEquals( -1, valueRecord.getLastCellNum() );
+        valueRecord.insertCell( newBlankRecord( 2, 2 ) );
+        assertEquals( 2, valueRecord.getLastCellNum() );
+        valueRecord.insertCell( newBlankRecord( 3, 3 ) );
+        assertEquals( 3, valueRecord.getLastCellNum() );
+
+        // Note: Removal doesn't currently reset the last column.  It probably should but it doesn't.
+        valueRecord.removeCell( newBlankRecord( 3, 3 ) );
+        assertEquals( 3, valueRecord.getLastCellNum() );
+
+    }
+
+
+    private static final class SerializerVisitor implements RecordVisitor {
+        private final byte[] _buf;
+        private int _writeIndex;
+        public SerializerVisitor(byte[] buf) {
+            _buf = buf;
+            _writeIndex = 0;
 
-		}
-		@Override
+        }
+        @Override
         public void visitRecord(org.apache.poi.hssf.record.Record r) {
-			r.serialize(_writeIndex, _buf);
-			_writeIndex += r.getRecordSize();
-		}
-		public int getWriteIndex() {
-			return _writeIndex;
-		}
-	}
+            r.serialize(_writeIndex, _buf);
+            _writeIndex += r.getRecordSize();
+        }
+        public int getWriteIndex() {
+            return _writeIndex;
+        }
+    }
 
     @Test
-	void testSerialize() {
-		byte[] expectedArray = HexRead.readFromString(""
-				+ "06 00 16 00 " // Formula
-				+ "01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
-				+ "01 02 06 00 " // Blank
-				+ "02 00 02 00 00 00");
-		byte[] actualArray = new byte[expectedArray.length];
-		List<org.apache.poi.hssf.record.Record> records = testData();
-		constructValueRecord(records);
-
-		SerializerVisitor sv = new SerializerVisitor(actualArray);
-		valueRecord.visitCellsForRow(1, sv);
-		valueRecord.visitCellsForRow(2, sv);
-		assertEquals(actualArray.length, sv.getWriteIndex());
-		assertArrayEquals(expectedArray, actualArray);
-	}
-
-	private static BlankRecord newBlankRecord() {
-		return newBlankRecord( 2, 2 );
-	}
-
-	private static BlankRecord newBlankRecord(int col, int row) {
-		BlankRecord blankRecord = new BlankRecord();
-		blankRecord.setRow( row );
-		blankRecord.setColumn( (short) col );
-		return blankRecord;
-	}
-
-	/**
-	 * Sometimes the 'shared formula' flag ({@code FormulaRecord.isSharedFormula()}) is set when
-	 * there is no corresponding SharedFormulaRecord available. SharedFormulaRecord definitions do
-	 * not span multiple sheets.  They are are only defined within a sheet, and thus they do not
-	 * have a sheet index field (only row and column range fields).<br>
-	 * So it is important that the code which locates the SharedFormulaRecord for each
-	 * FormulaRecord does not allow matches across sheets.<p>
-	 *
-	 * Prior to bugzilla 44449 (Feb 2008), POI {@code ValueRecordsAggregate.construct(int, List)}
-	 * allowed {@code SharedFormulaRecord}s to be erroneously used across sheets.  That incorrect
-	 * behaviour is shown by this test.<p>
-	 *
-	 * <b>Notes on how to produce the test spreadsheet</b>:</p>
-	 * The setup for this test (AbnormalSharedFormulaFlag.xls) is rather fragile, insomuchas
-	 * re-saving the file (either with Excel or POI) clears the flag.<br>
-	 * <ol>
-	 * <li>A new spreadsheet was created in Excel (File | New | Blank Workbook).</li>
-	 * <li>Sheet3 was deleted.</li>
-	 * <li>Sheet2!A1 formula was set to '="second formula"', and fill-dragged through A1:A8.</li>
-	 * <li>Sheet1!A1 formula was set to '="first formula"', and also fill-dragged through A1:A8.</li>
-	 * <li>Four rows on Sheet1 "5" through "8" were deleted ('delete rows' alt-E D, not 'clear' Del).</li>
-	 * <li>The spreadsheet was saved as AbnormalSharedFormulaFlag.xls.</li>
-	 * </ol>
-	 * Prior to the row delete action the spreadsheet has two {@code SharedFormulaRecord}s. One
-	 * for each sheet. To expose the bug, the shared formulas have been made to overlap.<br>
-	 * The row delete action (as described here) seems to to delete the
-	 * {@code SharedFormulaRecord} from Sheet1 (but not clear the 'shared formula' flags.<br>
-	 * There are other variations on this theme to create the same effect.
-	 *
-	 */
+    void testSerialize() {
+        byte[] expectedArray = HexRead.readFromString(""
+                + "06 00 16 00 " // Formula
+                + "01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
+                + "01 02 06 00 " // Blank
+                + "02 00 02 00 00 00");
+        byte[] actualArray = new byte[expectedArray.length];
+        List<org.apache.poi.hssf.record.Record> records = testData();
+        constructValueRecord(records);
+
+        SerializerVisitor sv = new SerializerVisitor(actualArray);
+        valueRecord.visitCellsForRow(1, sv);
+        valueRecord.visitCellsForRow(2, sv);
+        assertEquals(actualArray.length, sv.getWriteIndex());
+        assertArrayEquals(expectedArray, actualArray);
+    }
+
+    private static BlankRecord newBlankRecord() {
+        return newBlankRecord( 2, 2 );
+    }
+
+    private static BlankRecord newBlankRecord(int col, int row) {
+        BlankRecord blankRecord = new BlankRecord();
+        blankRecord.setRow( row );
+        blankRecord.setColumn( (short) col );
+        return blankRecord;
+    }
+
+    /**
+     * Sometimes the 'shared formula' flag ({@code FormulaRecord.isSharedFormula()}) is set when
+     * there is no corresponding SharedFormulaRecord available. SharedFormulaRecord definitions do
+     * not span multiple sheets.  They are are only defined within a sheet, and thus they do not
+     * have a sheet index field (only row and column range fields).<br>
+     * So it is important that the code which locates the SharedFormulaRecord for each
+     * FormulaRecord does not allow matches across sheets.<p>
+     *
+     * Prior to bugzilla 44449 (Feb 2008), POI {@code ValueRecordsAggregate.construct(int, List)}
+     * allowed {@code SharedFormulaRecord}s to be erroneously used across sheets.  That incorrect
+     * behaviour is shown by this test.<p>
+     *
+     * <b>Notes on how to produce the test spreadsheet</b>:</p>
+     * The setup for this test (AbnormalSharedFormulaFlag.xls) is rather fragile, insomuchas
+     * re-saving the file (either with Excel or POI) clears the flag.<br>
+     * <ol>
+     * <li>A new spreadsheet was created in Excel (File | New | Blank Workbook).</li>
+     * <li>Sheet3 was deleted.</li>
+     * <li>Sheet2!A1 formula was set to '="second formula"', and fill-dragged through A1:A8.</li>
+     * <li>Sheet1!A1 formula was set to '="first formula"', and also fill-dragged through A1:A8.</li>
+     * <li>Four rows on Sheet1 "5" through "8" were deleted ('delete rows' alt-E D, not 'clear' Del).</li>
+     * <li>The spreadsheet was saved as AbnormalSharedFormulaFlag.xls.</li>
+     * </ol>
+     * Prior to the row delete action the spreadsheet has two {@code SharedFormulaRecord}s. One
+     * for each sheet. To expose the bug, the shared formulas have been made to overlap.<br>
+     * The row delete action (as described here) seems to to delete the
+     * {@code SharedFormulaRecord} from Sheet1 (but not clear the 'shared formula' flags.<br>
+     * There are other variations on this theme to create the same effect.
+     *
+     */
     @Test
-	void testSpuriousSharedFormulaFlag() throws Exception {
+    void testSpuriousSharedFormulaFlag() throws Exception {
 
-		long actualCRC = getFileCRC(HSSFTestDataSamples.openSampleFileStream(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE));
-		long expectedCRC = 2277445406L;
-		if(actualCRC != expectedCRC) {
-			System.err.println("Expected crc " + expectedCRC  + " but got " + actualCRC);
-			throw failUnexpectedTestFileChange();
-		}
-		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE);
-
-		HSSFSheet s = wb.getSheetAt(0); // Sheet1
-
-		String cellFormula;
-		cellFormula = getFormulaFromFirstCell(s, 0); // row "1"
-		// the problem is not observable in the first row of the shared formula
-		assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");
-
-		// but the problem is observable in rows 2,3,4
-		cellFormula = getFormulaFromFirstCell(s, 1); // row "2"
-		assertNotEquals("\"second formula\"", cellFormula, "found bug 44449 (Wrong SharedFormulaRecord was used).");
-
-		assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");
-
-		wb.close();
-	}
-	private static String getFormulaFromFirstCell(HSSFSheet s, int rowIx) {
-		return s.getRow(rowIx).getCell(0).getCellFormula();
-	}
-
-	/**
-	 * If someone opened this particular test file in Excel and saved it, the peculiar condition
-	 * which causes the target bug would probably disappear.  This test would then just succeed
-	 * regardless of whether the fix was present.  So a CRC check is performed to make it less easy
-	 * for that to occur.
-	 */
-	private static RuntimeException failUnexpectedTestFileChange() {
-		String msg = "Test file '" + ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE + "' has changed.  "
-			+ "This junit may not be properly testing for the target bug.  "
-			+ "Either revert the test file or ensure that the new version "
-			+ "has the right characteristics to test the target bug.";
-		// A breakpoint in ValueRecordsAggregate.handleMissingSharedFormulaRecord(FormulaRecord)
-		// should get hit during parsing of Sheet1.
-		// If the test spreadsheet is created as directed, this condition should occur.
-		// It is easy to upset the test spreadsheet (for example re-saving will destroy the
-		// peculiar condition we are testing for).
-		throw new RuntimeException(msg);
-	}
-
-	/**
-	 * gets a CRC checksum for the content of a file
-	 */
-	private static long getFileCRC(InputStream is) {
-		CRC32 crc = new CRC32();
-		byte[] buf = new byte[2048];
-		try {
-			while(true) {
-				int bytesRead = is.read(buf);
-				if(bytesRead < 1) {
-					break;
-				}
-				crc.update(buf, 0, bytesRead);
-			}
-			is.close();
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
+        long actualCRC = getFileCRC(HSSFTestDataSamples.openSampleFileStream(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE));
+        long expectedCRC = 2277445406L;
+        if(actualCRC != expectedCRC) {
+            System.err.println("Expected crc " + expectedCRC  + " but got " + actualCRC);
+            throw failUnexpectedTestFileChange();
+        }
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE);
+
+        HSSFSheet s = wb.getSheetAt(0); // Sheet1
+
+        String cellFormula;
+        cellFormula = getFormulaFromFirstCell(s, 0); // row "1"
+        // the problem is not observable in the first row of the shared formula
+        assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");
+
+        // but the problem is observable in rows 2,3,4
+        cellFormula = getFormulaFromFirstCell(s, 1); // row "2"
+        assertNotEquals("\"second formula\"", cellFormula, "found bug 44449 (Wrong SharedFormulaRecord was used).");
+
+        assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");
+
+        wb.close();
+    }
+    private static String getFormulaFromFirstCell(HSSFSheet s, int rowIx) {
+        return s.getRow(rowIx).getCell(0).getCellFormula();
+    }
+
+    /**
+     * If someone opened this particular test file in Excel and saved it, the peculiar condition
+     * which causes the target bug would probably disappear.  This test would then just succeed
+     * regardless of whether the fix was present.  So a CRC check is performed to make it less easy
+     * for that to occur.
+     */
+    private static RuntimeException failUnexpectedTestFileChange() {
+        String msg = "Test file '" + ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE + "' has changed.  "
+            + "This junit may not be properly testing for the target bug.  "
+            + "Either revert the test file or ensure that the new version "
+            + "has the right characteristics to test the target bug.";
+        // A breakpoint in ValueRecordsAggregate.handleMissingSharedFormulaRecord(FormulaRecord)
+        // should get hit during parsing of Sheet1.
+        // If the test spreadsheet is created as directed, this condition should occur.
+        // It is easy to upset the test spreadsheet (for example re-saving will destroy the
+        // peculiar condition we are testing for).
+        throw new RuntimeException(msg);
+    }
+
+    /**
+     * gets a CRC checksum for the content of a file
+     */
+    private static long getFileCRC(InputStream is) {
+        CRC32 crc = new CRC32();
+        byte[] buf = new byte[2048];
+        try {
+            while(true) {
+                int bytesRead = is.read(buf);
+                if(bytesRead < 1) {
+                    break;
+                }
+                crc.update(buf, 0, bytesRead);
+            }
+            is.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
 
-		return crc.getValue();
-	}
+        return crc.getValue();
+    }
 
     @Test
-	void testRemoveNewRow_bug46312() throws IOException {
-		// To make bug occur, rowIndex needs to be >= ValueRecordsAggregate.records.length
-		int rowIndex = 30;
-
-		ValueRecordsAggregate vra = new ValueRecordsAggregate();
-		// bug 46312 - Specified rowIndex 30 is outside the allowable range (0..30)
-		assertDoesNotThrow(() -> vra.removeAllCellsValuesForRow(rowIndex));
-
-		// same bug as demonstrated through usermodel API
-		try (HSSFWorkbook wb = new HSSFWorkbook()) {
-			HSSFSheet sheet = wb.createSheet();
-			HSSFRow row = sheet.createRow(rowIndex);
-
-			// must not add any cells to the new row if we want to see the bug
-			// row.createCell(0); // this causes ValueRecordsAggregate.records to auto-extend
-			assertDoesNotThrow(() -> sheet.createRow(rowIndex));
-		}
-	}
-
-	/**
-	 * Tests various manipulations of blank cells, to make sure that {@link MulBlankRecord}s
-	 * are use appropriately
-	 */
+    void testRemoveNewRow_bug46312() throws IOException {
+        // To make bug occur, rowIndex needs to be >= ValueRecordsAggregate.records.length
+        int rowIndex = 30;
+
+        ValueRecordsAggregate vra = new ValueRecordsAggregate();
+        // bug 46312 - Specified rowIndex 30 is outside the allowable range (0..30)
+        assertDoesNotThrow(() -> vra.removeAllCellsValuesForRow(rowIndex));
+
+        // same bug as demonstrated through usermodel API
+        try (HSSFWorkbook wb = new HSSFWorkbook()) {
+            HSSFSheet sheet = wb.createSheet();
+            HSSFRow row = sheet.createRow(rowIndex);
+
+            // must not add any cells to the new row if we want to see the bug
+            // row.createCell(0); // this causes ValueRecordsAggregate.records to auto-extend
+            assertDoesNotThrow(() -> sheet.createRow(rowIndex));
+        }
+    }
+
+    /**
+     * Tests various manipulations of blank cells, to make sure that {@link MulBlankRecord}s
+     * are use appropriately
+     */
     @Test
-	void testMultipleBlanks() {
-		BlankRecord brA2 = newBlankRecord(0, 1);
-		BlankRecord brB2 = newBlankRecord(1, 1);
-		BlankRecord brC2 = newBlankRecord(2, 1);
-		BlankRecord brD2 = newBlankRecord(3, 1);
-		BlankRecord brE2 = newBlankRecord(4, 1);
-		BlankRecord brB3 = newBlankRecord(1, 2);
-		BlankRecord brC3 = newBlankRecord(2, 2);
-
-		valueRecord.insertCell(brA2);
-		valueRecord.insertCell(brB2);
-		valueRecord.insertCell(brD2);
-		confirmMulBlank(3, 1, 1);
-
-		valueRecord.insertCell(brC3);
-		confirmMulBlank(4, 1, 2);
-
-		valueRecord.insertCell(brB3);
-		valueRecord.insertCell(brE2);
-		confirmMulBlank(6, 3, 0);
-
-		valueRecord.insertCell(brC2);
-		confirmMulBlank(7, 2, 0);
-
-		valueRecord.removeCell(brA2);
-		confirmMulBlank(6, 2, 0);
-
-		valueRecord.removeCell(brC2);
-		confirmMulBlank(5, 2, 1);
-
-		valueRecord.removeCell(brC3);
-		confirmMulBlank(4, 1, 2);
-	}
-
-	private void confirmMulBlank(int expectedTotalBlankCells,
-			int expectedNumberOfMulBlankRecords, int expectedNumberOfSingleBlankRecords) {
-		// assumed row ranges set-up by caller:
-		final int firstRow = 1;
-		final int lastRow = 2;
-
-
-		final class BlankStats {
-			public int countBlankCells;
-			public int countMulBlankRecords;
-			public int countSingleBlankRecords;
-		}
-
-		final BlankStats bs = new BlankStats();
-		RecordVisitor rv = r -> {
-			if (r instanceof MulBlankRecord) {
-				MulBlankRecord mbr = (MulBlankRecord) r;
-				bs.countMulBlankRecords++;
-				bs.countBlankCells += mbr.getNumColumns();
-			} else if (r instanceof BlankRecord) {
-				bs.countSingleBlankRecords++;
-				bs.countBlankCells++;
-			}
-		};
-
-		for (int rowIx = firstRow; rowIx <=lastRow; rowIx++) {
-			if (valueRecord.rowHasCells(rowIx)) {
-				valueRecord.visitCellsForRow(rowIx, rv);
-			}
-		}
-		assertEquals(expectedTotalBlankCells, bs.countBlankCells);
-		assertEquals(expectedNumberOfMulBlankRecords, bs.countMulBlankRecords);
-		assertEquals(expectedNumberOfSingleBlankRecords, bs.countSingleBlankRecords);
-	}
+    void testMultipleBlanks() {
+        BlankRecord brA2 = newBlankRecord(0, 1);
+        BlankRecord brB2 = newBlankRecord(1, 1);
+        BlankRecord brC2 = newBlankRecord(2, 1);
+        BlankRecord brD2 = newBlankRecord(3, 1);
+        BlankRecord brE2 = newBlankRecord(4, 1);
+        BlankRecord brB3 = newBlankRecord(1, 2);
+        BlankRecord brC3 = newBlankRecord(2, 2);
+
+        valueRecord.insertCell(brA2);
+        valueRecord.insertCell(brB2);
+        valueRecord.insertCell(brD2);
+        confirmMulBlank(3, 1, 1);
+
+        valueRecord.insertCell(brC3);
+        confirmMulBlank(4, 1, 2);
+
+        valueRecord.insertCell(brB3);
+        valueRecord.insertCell(brE2);
+        confirmMulBlank(6, 3, 0);
+
+        valueRecord.insertCell(brC2);
+        confirmMulBlank(7, 2, 0);
+
+        valueRecord.removeCell(brA2);
+        confirmMulBlank(6, 2, 0);
+
+        valueRecord.removeCell(brC2);
+        confirmMulBlank(5, 2, 1);
+
+        valueRecord.removeCell(brC3);
+        confirmMulBlank(4, 1, 2);
+    }
+
+    private void confirmMulBlank(int expectedTotalBlankCells,
+            int expectedNumberOfMulBlankRecords, int expectedNumberOfSingleBlankRecords) {
+        // assumed row ranges set-up by caller:
+        final int firstRow = 1;
+        final int lastRow = 2;
+
+
+        final class BlankStats {
+            public int countBlankCells;
+            public int countMulBlankRecords;
+            public int countSingleBlankRecords;
+        }
+
+        final BlankStats bs = new BlankStats();
+        RecordVisitor rv = r -> {
+            if (r instanceof MulBlankRecord) {
+                MulBlankRecord mbr = (MulBlankRecord) r;
+                bs.countMulBlankRecords++;
+                bs.countBlankCells += mbr.getNumColumns();
+            } else if (r instanceof BlankRecord) {
+                bs.countSingleBlankRecords++;
+                bs.countBlankCells++;
+            }
+        };
+
+        for (int rowIx = firstRow; rowIx <=lastRow; rowIx++) {
+            if (valueRecord.rowHasCells(rowIx)) {
+                valueRecord.visitCellsForRow(rowIx, rv);
+            }
+        }
+        assertEquals(expectedTotalBlankCells, bs.countBlankCells);
+        assertEquals(expectedNumberOfMulBlankRecords, bs.countMulBlankRecords);
+        assertEquals(expectedNumberOfSingleBlankRecords, bs.countSingleBlankRecords);
+    }
 }



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