From 6367b8b74ee30e2b3a93c81f7555bda616124fe5 Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Tue, 9 Jul 2013 13:55:54 +0000 Subject: [PATCH] Add reproducing unit tests to TestUnfixedBugs for Bug 53798 and Bug 54071 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1501263 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xssf/usermodel/TestUnfixedBugs.java | 143 ++++++++++++++++-- .../spreadsheet/53798_shiftNegative_TMPL.xls | Bin 0 -> 27136 bytes .../spreadsheet/53798_shiftNegative_TMPL.xlsx | Bin 0 -> 9383 bytes test-data/spreadsheet/54071.xlsx | Bin 0 -> 9150 bytes 4 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 test-data/spreadsheet/53798_shiftNegative_TMPL.xls create mode 100644 test-data/spreadsheet/53798_shiftNegative_TMPL.xlsx create mode 100644 test-data/spreadsheet/54071.xlsx diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java index ce3fc2d04..cdeeaec31 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java @@ -17,25 +17,30 @@ package org.apache.poi.xssf.usermodel; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; -import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.TempFile; import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTFontImpl; /** * @author centic - * + * * This testcase contains tests for bugs that are yet to be fixed. Therefore, * the standard ant test target does not run these tests. Run this testcase with * the single-test target. The names of the tests usually correspond to the @@ -46,7 +51,7 @@ public final class TestUnfixedBugs extends TestCase { public void testBug54084Unicode() throws IOException { // sample XLSX with the same text-contents as the text-file above XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx"); - + verifyBug54084Unicode(wb); // OutputStream baos = new FileOutputStream("/tmp/test.xlsx"); @@ -55,7 +60,7 @@ public final class TestUnfixedBugs extends TestCase { // } finally { // baos.close(); // } - + // now write the file and read it back in XSSFWorkbook wbWritten = XSSFTestDataSamples.writeOutAndReadBack(wb); verifyBug54084Unicode(wbWritten); @@ -68,14 +73,134 @@ public final class TestUnfixedBugs extends TestCase { private void verifyBug54084Unicode(Workbook wb) throws UnsupportedEncodingException { // expected data is stored in UTF-8 in a text-file String testData = new String(HSSFTestDataSamples.getTestDataFileContent("54084 - Greek - beyond BMP.txt"), "UTF-8").trim(); - + Sheet sheet = wb.getSheetAt(0); Row row = sheet.getRow(0); Cell cell = row.getCell(0); - + String value = cell.getStringCellValue(); //System.out.println(value); - + assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value); - } + } + + public void test54071() { + Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx"); + Sheet sheet = workbook.getSheetAt(0); + int rows = sheet.getPhysicalNumberOfRows(); + System.out.println(">> file rows is:"+(rows-1)+" <<"); + Row title = sheet.getRow(0); + + for (int row = 1; row < rows; row++) { + Row rowObj = sheet.getRow(row); + for (int col = 0; col < 1; col++) { + String titleName = title.getCell(col).toString(); + Cell cell = rowObj.getCell(col); + if (titleName.startsWith("time")) { + // here the output will produce ...59 or ...58 for the rows, probably POI is + // doing some different rounding or some other small difference... + System.out.println("==Time:"+cell.getDateCellValue()); + } + } + } + } + + public void testBug53798XLSX() throws IOException { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("53798_shiftNegative_TMPL.xlsx"); + File xlsOutput = TempFile.createTempFile("testBug53798", ".xlsx"); + bug53798Work(wb, xlsOutput); + } + + // Disabled because shift rows is not yet implemented for SXSSFWorkbook + public void disabled_testBug53798XLSXStream() throws IOException { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("53798_shiftNegative_TMPL.xlsx"); + File xlsOutput = TempFile.createTempFile("testBug53798", ".xlsx"); + bug53798Work(new SXSSFWorkbook(wb), xlsOutput); + } + + public void testBug53798XLS() throws IOException { + Workbook wb = HSSFTestDataSamples.openSampleWorkbook("53798_shiftNegative_TMPL.xls"); + File xlsOutput = TempFile.createTempFile("testBug53798", ".xls"); + bug53798Work(wb, xlsOutput); + } + + private void bug53798Work(Workbook wb, File xlsOutput) throws IOException { + Sheet testSheet = wb.getSheetAt(0); + + testSheet.shiftRows(2, 2, 1); + + saveAndReloadReport(wb, xlsOutput); + + // 1) corrupted xlsx (unreadable data in the first row of a shifted group) already comes about + // when shifted by less than -1 negative amount (try -2) + testSheet.shiftRows(3, 3, -1); + + saveAndReloadReport(wb, xlsOutput); + + testSheet.shiftRows(2, 2, 1); + + saveAndReloadReport(wb, xlsOutput); + + Row newRow = null; + Cell newCell = null; + // 2) attempt to create a new row IN PLACE of a removed row by a negative shift causes corrupted + // xlsx file with unreadable data in the negative shifted row. + // NOTE it's ok to create any other row. + newRow = testSheet.createRow(3); + + saveAndReloadReport(wb, xlsOutput); + + newCell = newRow.createCell(0); + + saveAndReloadReport(wb, xlsOutput); + + newCell.setCellValue("new Cell in row "+newRow.getRowNum()); + + saveAndReloadReport(wb, xlsOutput); + + // 3) once a negative shift has been made any attempt to shift another group of rows + // (note: outside of previously negative shifted rows) by a POSITIVE amount causes POI exception: + // org.apache.xmlbeans.impl.values.XmlValueDisconnectedException. + // NOTE: another negative shift on another group of rows is successful, provided no new rows in + // place of previously shifted rows were attempted to be created as explained above. + testSheet.shiftRows(6, 7, 1); // -- CHANGE the shift to positive once the behaviour of + // the above has been tested + + saveAndReloadReport(wb, xlsOutput); + } + + private void saveAndReloadReport(Workbook wb, File outFile) throws IOException { + // run some method on the font to verify if it is "disconnected" already + //for(short i = 0;i < 256;i++) + { + Font font = wb.getFontAt((short)0); + if(font instanceof XSSFFont) { + XSSFFont xfont = (XSSFFont) wb.getFontAt((short)0); + CTFontImpl ctFont = (CTFontImpl) xfont.getCTFont(); + assertEquals(0, ctFont.sizeOfBArray()); + } + } + + FileOutputStream fileOutStream = new FileOutputStream(outFile); + wb.write(fileOutStream); + fileOutStream.close(); + //System.out.println("File \""+outFile.getName()+"\" has been saved successfully"); + + FileInputStream is = new FileInputStream(outFile); + try { + final Workbook newWB; + if(wb instanceof XSSFWorkbook) { + newWB = new XSSFWorkbook(is); + } else if(wb instanceof HSSFWorkbook) { + newWB = new HSSFWorkbook(is); + } else if(wb instanceof SXSSFWorkbook) { + newWB = new SXSSFWorkbook(new XSSFWorkbook(is)); + } else { + throw new IllegalStateException("Unknown workbook: " + wb); + } + assertNotNull(newWB.getSheet("test")); + } finally { + is.close(); + } + } } diff --git a/test-data/spreadsheet/53798_shiftNegative_TMPL.xls b/test-data/spreadsheet/53798_shiftNegative_TMPL.xls new file mode 100644 index 0000000000000000000000000000000000000000..1f9f48f4244a4b8ac82eb529d4e6cc694a9e8915 GIT binary patch literal 27136 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 V9K?cttZ{e*ScQC(l#u?o`X9Pq0`dR= literal 0 HcmV?d00001 diff --git a/test-data/spreadsheet/54071.xlsx b/test-data/spreadsheet/54071.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..be3a3e9b3821ff51b0142902cba4725f0f82a556 GIT binary patch literal 9150 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 literal 0 HcmV?d00001