/* ====================================================================
   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.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.poi.ddf.EscherDggRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ColumnInfoRecord;
import org.apache.poi.hssf.record.DimensionsRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.RecordInspector.RecordCollector;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.HexRead;
import org.junit.Test;

import junit.framework.AssertionFailedError;

/**
 * Unit test for the {@link InternalSheet} class.
 */
public final class TestSheet {
	private static InternalSheet createSheet(List<Record> inRecs) {
		return InternalSheet.createSheet(new RecordStream(inRecs, 0));
	}

	private static Record[] getSheetRecords(InternalSheet s, int offset) {
		RecordCollector rc = new RecordCollector();
		s.visitContainedRecords(rc, offset);
		return rc.getRecords();
	}

	@Test
	public void testCreateSheet() {
		// Check we're adding row and cell aggregates
		List<Record> records = new ArrayList<Record>();
		records.add(BOFRecord.createSheetBOF());
		records.add( new DimensionsRecord() );
		records.add(createWindow2Record());
		records.add(EOFRecord.instance);
		InternalSheet sheet = createSheet(records);
		Record[] outRecs = getSheetRecords(sheet, 0);

		int pos = 0;
		assertTrue(outRecs[pos++] instanceof BOFRecord );
		assertTrue(outRecs[pos++] instanceof IndexRecord);
		assertTrue(outRecs[pos++] instanceof DimensionsRecord);
		assertTrue(outRecs[pos++] instanceof WindowTwoRecord );
		assertTrue(outRecs[pos++] instanceof EOFRecord);
	}

	private static Record createWindow2Record() {
		WindowTwoRecord result = new WindowTwoRecord();
		result.setOptions(( short ) 0x6b6);
		result.setTopRow(( short ) 0);
		result.setLeftCol(( short ) 0);
		result.setHeaderColor(0x40);
		result.setPageBreakZoom(( short ) 0);
		result.setNormalZoom(( short ) 0);
		return result;
	}

	private static final class MergedCellListener implements RecordVisitor {

		private int _count;
		public MergedCellListener() {
			_count = 0;
		}
		@Override
        public void visitRecord(Record r) {
			if (r instanceof MergeCellsRecord) {
				_count++;
			}
		}
		public int getCount() {
			return _count;
		}
	}

    @Test
	public void testAddMergedRegion() {
		InternalSheet sheet = InternalSheet.createSheet();
		int regionsToAdd = 4096;

		//simple test that adds a load of regions
		for (int n = 0; n < regionsToAdd; n++)
		{
			int index = sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
			assertTrue("Merged region index expected to be " + n + " got " + index, index == n);
		}

		//test all the regions were indeed added
		assertTrue(sheet.getNumMergedRegions() == regionsToAdd);

		//test that the regions were spread out over the appropriate number of records
		MergedCellListener mcListener = new MergedCellListener();
		sheet.visitContainedRecords(mcListener, 0);
		int recordsAdded	= mcListener.getCount();
		int recordsExpected = regionsToAdd/1027;
		if ((regionsToAdd % 1027) != 0)
			recordsExpected++;
		assertTrue("The " + regionsToAdd + " merged regions should have been spread out over "
				+ recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
		// Check we can't add one with invalid date
		try {
			sheet.addMergedRegion(10, (short)10, 9, (short)12);
			fail("Expected an exception to occur");
		} catch(IllegalArgumentException e) {
			// occurs during successful test
			assertEquals("The 'to' row (9) must not be less than the 'from' row (10)", e.getMessage());
		}
		try {
			sheet.addMergedRegion(10, (short)10, 12, (short)9);
			fail("Expected an exception to occur");
		} catch(IllegalArgumentException e) {
			// occurs during successful test
			assertEquals("The 'to' col (9) must not be less than the 'from' col (10)", e.getMessage());
		}
	}

    @Test
	public void testRemoveMergedRegion() {
		InternalSheet sheet = InternalSheet.createSheet();
		int regionsToAdd = 4096;

		for (int n = 0; n < regionsToAdd; n++) {
			sheet.addMergedRegion(n, 0, n, 1);
		}

		int nSheetRecords = sheet.getRecords().size();

		//remove a third from the beginning
		for (int n = 0; n < regionsToAdd/3; n++)
		{
			sheet.removeMergedRegion(0);
			//assert they have been deleted
			assertEquals("Num of regions", regionsToAdd - n - 1, sheet.getNumMergedRegions());
		}

		// merge records are removed from within the MergedCellsTable,
		// so the sheet record count should not change
		assertEquals("Sheet Records", nSheetRecords, sheet.getRecords().size());
	}

	/**
	 * Bug: 22922 (Reported by Xuemin Guan)
	 * <p>
	 * Remove mergedregion fails when a sheet loses records after an initial CreateSheet
	 * fills up the records.
	 *
	 */
    @Test
	public void testMovingMergedRegion() {
		List<Record> records = new ArrayList<Record>();

		CellRangeAddress[] cras = {
			new CellRangeAddress(0, 1, 0, 2),
		};
		MergeCellsRecord merged = new MergeCellsRecord(cras, 0, cras.length);
		records.add(BOFRecord.createSheetBOF());
		records.add(new DimensionsRecord());
		records.add(new RowRecord(0));
		records.add(new RowRecord(1));
		records.add(new RowRecord(2));
		records.add(createWindow2Record());
		records.add(EOFRecord.instance);
		records.add(merged);

		InternalSheet sheet = createSheet(records);
		sheet.getRecords().remove(0); // TODO - what does this line do?

		//stub object to throw off list INDEX operations
		sheet.removeMergedRegion(0);
		assertEquals("Should be no more merged regions", 0, sheet.getNumMergedRegions());
	}

    @Test
	public void testGetMergedRegionAt() {
		//TODO
	}

    @Test
	public void testGetNumMergedRegions() {
		//TODO
	}

	/**
	 * Makes sure all rows registered for this sheet are aggregated, they were being skipped
	 *
	 */
    @Test
	public void testRowAggregation() {
		List<Record> records = new ArrayList<Record>();

		records.add(InternalSheet.createBOF());
		records.add(new DimensionsRecord());
		records.add(new RowRecord(0));
		records.add(new RowRecord(1));
		FormulaRecord formulaRecord = new FormulaRecord();
		formulaRecord.setCachedResultTypeString();
		records.add(formulaRecord);
		records.add(new StringRecord());
		records.add(new RowRecord(2));
		records.add(createWindow2Record());
		records.add(EOFRecord.instance);

		InternalSheet sheet = createSheet(records);
		assertNotNull("Row [2] was skipped", sheet.getRow(2));
	}

	/**
	 * Make sure page break functionality works (in memory)
	 *
	 */
    @Test
	public void testRowPageBreaks() {
		short colFrom = 0;
		short colTo = 255;

		InternalSheet worksheet = InternalSheet.createSheet();
		PageSettingsBlock sheet = worksheet.getPageSettings();
		sheet.setRowBreak(0, colFrom, colTo);

		assertTrue("no row break at 0", sheet.isRowBroken(0));
		assertEquals("1 row break available", 1, sheet.getNumRowBreaks());

		sheet.setRowBreak(0, colFrom, colTo);
		sheet.setRowBreak(0, colFrom, colTo);

		assertTrue("no row break at 0", sheet.isRowBroken(0));
		assertEquals("1 row break available", 1, sheet.getNumRowBreaks());

		sheet.setRowBreak(10, colFrom, colTo);
		sheet.setRowBreak(11, colFrom, colTo);

		assertTrue("no row break at 10", sheet.isRowBroken(10));
		assertTrue("no row break at 11", sheet.isRowBroken(11));
		assertEquals("3 row break available", 3, sheet.getNumRowBreaks());


		boolean is10 = false;
		boolean is0 = false;
		boolean is11 = false;

		int[] rowBreaks = sheet.getRowBreaks();
		for (int main : rowBreaks) {
			if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
			if (main == 0)	 is0 = true;
			if (main == 10) is10= true;
			if (main == 11) is11 = true;
		}

		assertTrue("one of the breaks didnt make it", is0 && is10 && is11);

		sheet.removeRowBreak(11);
		assertFalse("row should be removed", sheet.isRowBroken(11));

		sheet.removeRowBreak(0);
		assertFalse("row should be removed", sheet.isRowBroken(0));

		sheet.removeRowBreak(10);
		assertFalse("row should be removed", sheet.isRowBroken(10));

		assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
	}

	/**
	 * Make sure column pag breaks works properly (in-memory)
	 *
	 */
    @Test
	public void testColPageBreaks() {
		short rowFrom = 0;
		short rowTo = (short)65535;

		InternalSheet worksheet = InternalSheet.createSheet();
		PageSettingsBlock sheet = worksheet.getPageSettings();
		sheet.setColumnBreak((short)0, rowFrom, rowTo);

		assertTrue("no col break at 0", sheet.isColumnBroken(0));
		assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());

		sheet.setColumnBreak((short)0, rowFrom, rowTo);

		assertTrue("no col break at 0", sheet.isColumnBroken(0));
		assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());

		sheet.setColumnBreak((short)1, rowFrom, rowTo);
		sheet.setColumnBreak((short)10, rowFrom, rowTo);
		sheet.setColumnBreak((short)15, rowFrom, rowTo);

		assertTrue("no col break at 1", sheet.isColumnBroken(1));
		assertTrue("no col break at 10", sheet.isColumnBroken(10));
		assertTrue("no col break at 15", sheet.isColumnBroken(15));
		assertEquals("4 col break available", 4, sheet.getNumColumnBreaks());

		boolean is10 = false;
		boolean is0 = false;
		boolean is1 = false;
		boolean is15 = false;

		int[] colBreaks = sheet.getColumnBreaks();
		for (int main : colBreaks) {
			if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
			if (main == 0)  is0 = true;
			if (main == 1)  is1 = true;
			if (main == 10) is10= true;
			if (main == 15) is15 = true;
		}

		assertTrue("one of the breaks didnt make it", is0 && is1 && is10 && is15);

		sheet.removeColumnBreak(15);
		assertFalse("column break should not be there", sheet.isColumnBroken(15));

		sheet.removeColumnBreak(0);
		assertFalse("column break should not be there", sheet.isColumnBroken(0));

		sheet.removeColumnBreak(1);
		assertFalse("column break should not be there", sheet.isColumnBroken(1));

		sheet.removeColumnBreak(10);
		assertFalse("column break should not be there", sheet.isColumnBroken(10));

		assertEquals("no more breaks", 0, sheet.getNumColumnBreaks());
	}

	/**
	 * test newly added method Sheet.getXFIndexForColAt(..)
	 * works as designed.
	 */
    @Test
	public void testXFIndexForColumn() {
		final short TEST_IDX = 10;
		final short DEFAULT_IDX = 0xF; // 15
		short xfindex = Short.MIN_VALUE;
		InternalSheet sheet = InternalSheet.createSheet();

		// without ColumnInfoRecord
		xfindex = sheet.getXFIndexForColAt((short) 0);
		assertEquals(DEFAULT_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 1);
		assertEquals(DEFAULT_IDX, xfindex);

		ColumnInfoRecord nci = new ColumnInfoRecord();
		sheet._columnInfos.insertColumn(nci);

		// single column ColumnInfoRecord
		nci.setFirstColumn((short) 2);
		nci.setLastColumn((short) 2);
		nci.setXFIndex(TEST_IDX);
		xfindex = sheet.getXFIndexForColAt((short) 0);
		assertEquals(DEFAULT_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 1);
		assertEquals(DEFAULT_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 2);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 3);
		assertEquals(DEFAULT_IDX, xfindex);

		// ten column ColumnInfoRecord
		nci.setFirstColumn((short) 2);
		nci.setLastColumn((short) 11);
		nci.setXFIndex(TEST_IDX);
		xfindex = sheet.getXFIndexForColAt((short) 1);
		assertEquals(DEFAULT_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 2);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 6);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 11);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 12);
		assertEquals(DEFAULT_IDX, xfindex);

		// single column ColumnInfoRecord starting at index 0
		nci.setFirstColumn((short) 0);
		nci.setLastColumn((short) 0);
		nci.setXFIndex(TEST_IDX);
		xfindex = sheet.getXFIndexForColAt((short) 0);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 1);
		assertEquals(DEFAULT_IDX, xfindex);

		// ten column ColumnInfoRecord starting at index 0
		nci.setFirstColumn((short) 0);
		nci.setLastColumn((short) 9);
		nci.setXFIndex(TEST_IDX);
		xfindex = sheet.getXFIndexForColAt((short) 0);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 7);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 9);
		assertEquals(TEST_IDX, xfindex);
		xfindex = sheet.getXFIndexForColAt((short) 10);
		assertEquals(DEFAULT_IDX, xfindex);
	}

	private static final class SizeCheckingRecordVisitor implements RecordVisitor {

		private int _totalSize;
		public SizeCheckingRecordVisitor() {
			_totalSize = 0;
		}
		@Override
        public void visitRecord(Record r) {

			int estimatedSize=r.getRecordSize();
			byte[] buf = new byte[estimatedSize];
			int serializedSize = r.serialize(0, buf);
			if (estimatedSize != serializedSize) {
				throw new AssertionFailedError("serialized size mismatch for record ("
						+ r.getClass().getName() + ")");
			}
			_totalSize += estimatedSize;
		}
		public int getTotalSize() {
			return _totalSize;
		}
	}
	/**
	 * Prior to bug 45066, POI would get the estimated sheet size wrong
	 * when an <tt>UncalcedRecord</tt> was present.<p/>
	 */
    @Test
	public void testUncalcSize_bug45066() {

		List<Record> records = new ArrayList<Record>();
		records.add(BOFRecord.createSheetBOF());
		records.add(new UncalcedRecord());
		records.add(new DimensionsRecord());
		records.add(createWindow2Record());
		records.add(EOFRecord.instance);
		InternalSheet sheet = createSheet(records);

		// The original bug was due to different logic for collecting records for sizing and
		// serialization. The code has since been refactored into a single method for visiting
		// all contained records.  Now this test is much less interesting
		SizeCheckingRecordVisitor scrv = new SizeCheckingRecordVisitor();
		sheet.visitContainedRecords(scrv, 0);
		assertEquals(90, scrv.getTotalSize());
	}

	/**
	 * Prior to bug 45145 <tt>RowRecordsAggregate</tt> and <tt>ValueRecordsAggregate</tt> could
	 * sometimes occur in reverse order.  This test reproduces one of those situations and makes
	 * sure that RRA comes before VRA.<br/>
	 *
	 * The code here represents a normal POI use case where a spreadsheet is created from scratch.
	 */
    @Test
	public void testRowValueAggregatesOrder_bug45145() {

		InternalSheet sheet = InternalSheet.createSheet();

		RowRecord rr = new RowRecord(5);
		sheet.addRow(rr);

		CellValueRecordInterface cvr = new BlankRecord();
		cvr.setColumn((short)0);
		cvr.setRow(5);
		sheet.addValueRecord(5, cvr);


		int dbCellRecordPos = getDbCellRecordPos(sheet);
		if (dbCellRecordPos == 252) {
			// The overt symptom of the bug
			// DBCELL record pos is calculated wrong if VRA comes before RRA
			throw new AssertionFailedError("Identified  bug 45145");
		}

//		if (false) {
//			// make sure that RRA and VRA are in the right place
//			// (Aug 2008) since the VRA is now part of the RRA, there is much less chance that
//			// they could get out of order. Still, one could write serialize the sheet here,
//			// and read back with EventRecordFactory to make sure...
//		}
		assertEquals(242, dbCellRecordPos);
	}

	/**
	 * @return the value calculated for the position of the first DBCELL record for this sheet.
	 * That value is found on the IndexRecord.
	 */
	private static int getDbCellRecordPos(InternalSheet sheet) {

		MyIndexRecordListener myIndexListener = new MyIndexRecordListener();
		sheet.visitContainedRecords(myIndexListener, 0);
		IndexRecord indexRecord = myIndexListener.getIndexRecord();
		int dbCellRecordPos = indexRecord.getDbcellAt(0);
		return dbCellRecordPos;
	}

	private static final class MyIndexRecordListener implements RecordVisitor {

		private IndexRecord _indexRecord;
		public MyIndexRecordListener() {
			// no-arg constructor
		}
		public IndexRecord getIndexRecord() {
			return _indexRecord;
		}
		@Override
        public void visitRecord(Record r) {
			if (r instanceof IndexRecord) {
				if (_indexRecord != null) {
					throw new RuntimeException("too many index records");
				}
				_indexRecord = (IndexRecord)r;
			}
		}
	}

	/**
	 * Checks for bug introduced around r682282-r683880 that caused a second GUTS records
	 * which in turn got the dimensions record out of alignment
	 */
    @Test
	public void testGutsRecord_bug45640() {

		InternalSheet sheet = InternalSheet.createSheet();
		sheet.addRow(new RowRecord(0));
		sheet.addRow(new RowRecord(1));
		sheet.groupRowRange( 0, 1, true );
		sheet.toString();
		List<RecordBase> recs = sheet.getRecords();
		int count=0;
		for(int i=0; i< recs.size(); i++) {
			if (recs.get(i) instanceof GutsRecord) {
				count++;
			}
		}
		if (count == 2) {
			throw new AssertionFailedError("Identified bug 45640");
		}
		assertEquals(1, count);
	}

    @Test
	public void testMisplacedMergedCellsRecords_bug45699() throws Exception {
		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex45698-22488.xls");

		HSSFSheet sheet = wb.getSheetAt(0);
		HSSFRow row = sheet.getRow(3);
		HSSFCell cell = row.getCell(4);
		if (cell == null) {
			fail("Identified bug 45699");
		}
		assertEquals("Informations", cell.getRichStringCellValue().getString());
		
		wb.close();
	}
	/**
	 * In 3.1, setting margins between creating first row and first cell caused an exception.
	 */
    @Test
	public void testSetMargins_bug45717() throws Exception {
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("Vorschauliste");
		HSSFRow row = sheet.createRow(0);

		sheet.setMargin(HSSFSheet.LeftMargin, 0.3);
		try {
			row.createCell(0);
		} catch (IllegalStateException e) {
			if (e.getMessage().equals("Cannot create value records before row records exist")) {
				fail("Identified bug 45717");
			}
			throw e;
		} finally {
		    workbook.close();
		}
	}

	/**
	 * Some apps seem to write files with missing DIMENSION records.
	 * Excel(2007) tolerates this, so POI should too.
	 */
    @Test
	public void testMissingDims() {

		int rowIx = 5;
		int colIx = 6;
		NumberRecord nr = new NumberRecord();
		nr.setRow(rowIx);
		nr.setColumn((short) colIx);
		nr.setValue(3.0);

		List<Record> inRecs = new ArrayList<Record>();
		inRecs.add(BOFRecord.createSheetBOF());
		inRecs.add(new RowRecord(rowIx));
		inRecs.add(nr);
		inRecs.add(createWindow2Record());
		inRecs.add(EOFRecord.instance);
		InternalSheet sheet;
		try {
			sheet = createSheet(inRecs);
		} catch (RuntimeException e) {
			if ("DimensionsRecord was not found".equals(e.getMessage())) {
				throw new AssertionFailedError("Identified bug 46206");
			}
			throw e;
		}

		RecordCollector rv = new RecordCollector();
		sheet.visitContainedRecords(rv, rowIx);
		Record[] outRecs = rv.getRecords();
		assertEquals(8, outRecs.length);
		DimensionsRecord dims = (DimensionsRecord) outRecs[5];
		assertEquals(rowIx, dims.getFirstRow());
		assertEquals(rowIx, dims.getLastRow());
		assertEquals(colIx, dims.getFirstCol());
		assertEquals(colIx, dims.getLastCol());
	}

	/**
	 * Prior to the fix for bug 46547, shifting formulas would have the side-effect
	 * of creating a {@link ConditionalFormattingTable}.  There was no impairment to
	 * functionality since empty record aggregates are equivalent to missing record
	 * aggregates. However, since this unnecessary creation helped expose bug 46547b,
	 * and since there is a slight performance hit the fix was made to avoid it.
	 */
    @Test
	public void testShiftFormulasAddCondFormat_bug46547() {
		// Create a sheet with data validity (similar to bugzilla attachment id=23131).
		InternalSheet sheet = InternalSheet.createSheet();

		List<RecordBase> sheetRecs = sheet.getRecords();
		assertEquals(23, sheetRecs.size());

		FormulaShifter shifter = FormulaShifter.createForRowShift(0, "", 0, 0, 1, SpreadsheetVersion.EXCEL97);
		sheet.updateFormulasAfterCellShift(shifter, 0);
		if (sheetRecs.size() == 24 && sheetRecs.get(22) instanceof ConditionalFormattingTable) {
			throw new AssertionFailedError("Identified bug 46547a");
		}
		assertEquals(23, sheetRecs.size());
	}
	/**
	 * Bug 46547 happened when attempting to add conditional formatting to a sheet
	 * which already had data validity constraints.
	 */
    @Test
	public void testAddCondFormatAfterDataValidation_bug46547() {
		// Create a sheet with data validity (similar to bugzilla attachment id=23131).
		InternalSheet sheet = InternalSheet.createSheet();
		sheet.getOrCreateDataValidityTable();

		ConditionalFormattingTable cft;
		// attempt to add conditional formatting
		try {

			cft = sheet.getConditionalFormattingTable(); // lazy getter
		} catch (ClassCastException e) {
			throw new AssertionFailedError("Identified bug 46547b");
		}
		assertNotNull(cft);
	}

    @Test
	public void testCloneMulBlank_bug46776() {
		Record[]  recs = {
				InternalSheet.createBOF(),
				new DimensionsRecord(),
				new RowRecord(1),
				new MulBlankRecord(1, 3, new short[] { 0x0F, 0x0F, 0x0F, } ),
				new RowRecord(2),
				createWindow2Record(),
				EOFRecord.instance,
		};

		InternalSheet sheet = createSheet(Arrays.asList(recs));

		InternalSheet sheet2;
		try {
			sheet2 = sheet.cloneSheet();
		} catch (RuntimeException e) {
			if (e.getMessage().equals("The class org.apache.poi.hssf.record.MulBlankRecord needs to define a clone method")) {
				throw new AssertionFailedError("Identified bug 46776");
			}
			throw e;
		}

		RecordCollector rc = new RecordCollector();
		sheet2.visitContainedRecords(rc, 0);
		Record[] clonedRecs = rc.getRecords();
		assertEquals(recs.length+2, clonedRecs.length); // +2 for INDEX and DBCELL
	}

    @Test
    public void testCreateAggregate() {
        String msoDrawingRecord1 =
                "0F 00 02 F0 20 01 00 00 10 00 08 F0 08 00 00 00 \n" +
                "03 00 00 00 02 04 00 00 0F 00 03 F0 08 01 00 00 \n" +
                "0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 00 \n" +
                "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \n" +
                "02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 00 \n" +
                "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 \n" +
                "01 04 00 00 00 0A 00 00 73 00 0B F0 2A 00 00 00 \n" +
                "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 \n" +
                "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 \n" +
                "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 \n" +
                "00 00 00 00 01 00 54 00 05 00 45 00 01 00 88 03 \n" +
                "05 00 94 00 00 00 11 F0 00 00 00 00";

        String msoDrawingRecord2 =
                "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 " +
                "02 04 00 00 80 0A 00 00 73 00 0B F0 2A 00 00 00 " +
                "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 " +
                "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 " +
                "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 " +
                "00 00 00 00 01 00 8D 03 05 00 E4 00 03 00 4D 03 " +
                "0B 00 0C 00 00 00 11 F0 00 00 00 00";

        DrawingRecord d1 = new DrawingRecord();
        d1.setData( HexRead.readFromString( msoDrawingRecord1 ) );

        ObjRecord r1 = new ObjRecord();

        DrawingRecord d2 = new DrawingRecord();
        d2.setData( HexRead.readFromString( msoDrawingRecord2 ) );

        TextObjectRecord r2 = new TextObjectRecord();
        r2.setStr(new HSSFRichTextString("Aggregated"));
        NoteRecord n2 = new NoteRecord();

        List<Record> recordStream = new ArrayList<Record>();
        recordStream.add(InternalSheet.createBOF());
        recordStream.add( d1 );
        recordStream.add( r1 );
        recordStream.add(createWindow2Record());
        recordStream.add(EOFRecord.instance);

        confirmAggregatedRecords(recordStream);


        recordStream = new ArrayList<Record>();
        recordStream.add(InternalSheet.createBOF());
        recordStream.add( d1 );
        recordStream.add( r1 );
        recordStream.add( d2 );
        recordStream.add( r2 );
        recordStream.add(createWindow2Record());
        recordStream.add(EOFRecord.instance);

        confirmAggregatedRecords(recordStream);

        recordStream = new ArrayList<Record>();
        recordStream.add(InternalSheet.createBOF());
        recordStream.add( d1 );
        recordStream.add( r1 );
        recordStream.add( d2 );
        recordStream.add( r2 );
        recordStream.add( n2 );
        recordStream.add(createWindow2Record());
        recordStream.add(EOFRecord.instance);

        confirmAggregatedRecords(recordStream);
     }

    private void confirmAggregatedRecords(List<Record> recordStream){
        InternalSheet sheet = InternalSheet.createSheet();
        sheet.getRecords().clear();
        sheet.getRecords().addAll(recordStream);

        List<RecordBase> sheetRecords = sheet.getRecords();

        DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord() );
        sheet.aggregateDrawingRecords(drawingManager, false);

        assertEquals(4, sheetRecords.size());
        assertEquals(BOFRecord.sid, ((Record)sheetRecords.get(0)).getSid());
        assertEquals(EscherAggregate.sid, ((Record)sheetRecords.get(1)).getSid());
        assertEquals(WindowTwoRecord.sid, ((Record)sheetRecords.get(2)).getSid());
        assertEquals(EOFRecord.sid, ((Record)sheetRecords.get(3)).getSid());
    }

    @Test
    public void testSheetDimensions() throws IOException{
        InternalSheet sheet = InternalSheet.createSheet();
        DimensionsRecord dimensions = (DimensionsRecord)sheet.findFirstRecordBySid(DimensionsRecord.sid);
        assertEquals(0, dimensions.getFirstCol());
        assertEquals(0, dimensions.getFirstRow());
        assertEquals(1, dimensions.getLastCol());  // plus pne
        assertEquals(1, dimensions.getLastRow());  // plus pne

        RowRecord rr = new RowRecord(0);
        sheet.addRow(rr);

        assertEquals(0, dimensions.getFirstCol());
        assertEquals(0, dimensions.getFirstRow());
        assertEquals(1, dimensions.getLastCol());
        assertEquals(1, dimensions.getLastRow());

        CellValueRecordInterface cvr;

        cvr = new BlankRecord();
        cvr.setColumn((short)0);
        cvr.setRow(0);
        sheet.addValueRecord(0, cvr);

        assertEquals(0, dimensions.getFirstCol());
        assertEquals(0, dimensions.getFirstRow());
        assertEquals(1, dimensions.getLastCol());
        assertEquals(1, dimensions.getLastRow());

        cvr = new BlankRecord();
        cvr.setColumn((short)1);
        cvr.setRow(0);
        sheet.addValueRecord(0, cvr);

        assertEquals(0, dimensions.getFirstCol());
        assertEquals(0, dimensions.getFirstRow());
        assertEquals(2, dimensions.getLastCol());   //YK:  failed until Bugzilla 53414 was fixed
        assertEquals(1, dimensions.getLastRow());
    }
}
