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 [43/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/ss/util/NumberRenderingSpreadsheetGenerator.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberRenderingSpreadsheetGenerator.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberRenderingSpreadsheetGenerator.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberRenderingSpreadsheetGenerator.java Sat May 22 20:56:44 2021
@@ -44,198 +44,198 @@ import org.apache.poi.util.HexRead;
*/
public class NumberRenderingSpreadsheetGenerator {
- private static final class SheetWriter {
+ private static final class SheetWriter {
- private final HSSFSheet _sheet;
- private int _rowIndex;
- private final List<Long> _replacementNaNs;
-
- public SheetWriter(HSSFWorkbook wb) {
- HSSFSheet sheet = wb.createSheet("Sheet1");
-
- writeHeaderRow(wb, sheet);
- _sheet = sheet;
- _rowIndex = 1;
- _replacementNaNs = new ArrayList<>();
- }
-
- void addTestRow(long rawBits, String expectedExcelRendering) {
- writeDataRow(_sheet, _rowIndex++, rawBits, expectedExcelRendering);
- if(Double.isNaN(Double.longBitsToDouble(rawBits))) {
- _replacementNaNs.add(Long.valueOf(rawBits));
- }
- }
-
- public long[] getReplacementNaNs() {
- int nRepls = _replacementNaNs.size();
- long[] result = new long[nRepls];
- for (int i = 0; i < nRepls; i++) {
- result[i] = _replacementNaNs.get(i).longValue();
- }
- return result;
- }
-
- }
- /** 0x7ff8000000000000 encoded in little endian order */
- private static final byte[] JAVA_NAN_BYTES = HexRead.readFromString("00 00 00 00 00 00 F8 7F");
-
- private static void writeHeaderCell(HSSFRow row, int i, String text, HSSFCellStyle style) {
- HSSFCell cell = row.createCell(i);
- cell.setCellValue(new HSSFRichTextString(text));
- cell.setCellStyle(style);
- }
- static void writeHeaderRow(HSSFWorkbook wb, HSSFSheet sheet) {
- sheet.setColumnWidth(0, 3000);
- sheet.setColumnWidth(1, 6000);
- sheet.setColumnWidth(2, 6000);
- sheet.setColumnWidth(3, 6000);
- sheet.setColumnWidth(4, 6000);
- sheet.setColumnWidth(5, 1600);
- sheet.setColumnWidth(6, 20000);
- HSSFRow row = sheet.createRow(0);
- HSSFCellStyle style = wb.createCellStyle();
- HSSFFont font = wb.createFont();
- font.setBold(true);
- style.setFont(font);
- writeHeaderCell(row, 0, "Value", style);
- writeHeaderCell(row, 1, "Raw Long Bits", style);
- writeHeaderCell(row, 2, "JDK Double Rendering", style);
- writeHeaderCell(row, 3, "Actual Rendering", style);
- writeHeaderCell(row, 4, "Expected Rendering", style);
- writeHeaderCell(row, 5, "Match", style);
- writeHeaderCell(row, 6, "Java Metadata", style);
- }
- static void writeDataRow(HSSFSheet sheet, int rowIx, long rawLongBits, String expectedExcelRendering) {
- double d = Double.longBitsToDouble(rawLongBits);
- HSSFRow row = sheet.createRow(rowIx);
-
- int rowNum = rowIx + 1;
- String cel0ref = "A" + rowNum;
- String rawBitsText = formatLongAsHex(rawLongBits);
- String jmExpr = "'ec(" + rawBitsText + ", ''\" & C" + rowNum + " & \"'', ''\" & D" + rowNum + " & \"''),'";
-
- // The 'Match' column will contain 'OK' if the metadata (from NumberToTextConversionExamples)
- // matches Excel's rendering.
- String matchExpr = "if(D" + rowNum + "=E" + rowNum + ", \"OK\", \"ERROR\")";
-
- row.createCell(0).setCellValue(d);
- row.createCell(1).setCellValue(new HSSFRichTextString(rawBitsText));
- row.createCell(2).setCellValue(new HSSFRichTextString(Double.toString(d)));
- row.createCell(3).setCellFormula("\"\" & " + cel0ref);
- row.createCell(4).setCellValue(new HSSFRichTextString(expectedExcelRendering));
- row.createCell(5).setCellFormula(matchExpr);
- row.createCell(6).setCellFormula(jmExpr.replaceAll("'", "\""));
-
-// if (false) {
-// // for observing arithmetic near numeric range boundaries
-// row.createCell(7).setCellFormula(cel0ref + " * 1.0001");
-// row.createCell(8).setCellFormula(cel0ref + " / 1.0001");
-// }
- }
-
- private static String formatLongAsHex(long l) {
- return HexDump.longToHex(l) + 'L';
- }
-
- public static void main(String[] args) {
- writeJavaDoc();
-
- HSSFWorkbook wb = new HSSFWorkbook();
- SheetWriter sw = new SheetWriter(wb);
-
- ExampleConversion[] exampleValues = NumberToTextConversionExamples.getExampleConversions();
- for (ExampleConversion example : exampleValues) {
- sw.addTestRow(example.getRawDoubleBits(), example.getExcelRendering());
- }
-
- File outputFile = new File("ExcelNumberRendering.xls");
-
- try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream();
- FileOutputStream os = new FileOutputStream(outputFile)) {
- wb.write(baos);
-
- byte[] fileContent = baos.toByteArray();
- replaceNaNs(fileContent, sw.getReplacementNaNs());
-
- os.write(fileContent);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- System.out.println("Finished writing '" + outputFile.getAbsolutePath() + "'");
- }
-
- public static void writeJavaDoc() {
-
- ExampleConversion[] exampleConversions = NumberToTextConversionExamples.getExampleConversions();
- for (ExampleConversion ec : exampleConversions) {
- String line = " * <tr><td>"
- + formatLongAsHex(ec.getRawDoubleBits())
- + "</td><td>" + Double.toString(ec.getDoubleValue())
- + "</td><td>" + ec.getExcelRendering() + "</td></tr>";
-
- System.out.println(line);
- }
- }
-
-
-
- private static void replaceNaNs(byte[] fileContent, long[] replacementNaNs) {
- int countFound = 0;
- for(int i=0; i<fileContent.length; i++) {
- if(isNaNBytes(fileContent, i)) {
- writeLong(fileContent, i, replacementNaNs[countFound]);
- countFound++;
- }
- }
- if (countFound < replacementNaNs.length) {
- throw new RuntimeException("wrong repl count");
- }
-
- }
-
- private static void writeLong(byte[] bb, int i, long val) {
- /*String oldVal =*/ interpretLong(bb, i);
- bb[i+7] = (byte) (val >> 56);
- bb[i+6] = (byte) (val >> 48);
- bb[i+5] = (byte) (val >> 40);
- bb[i+4] = (byte) (val >> 32);
- bb[i+3] = (byte) (val >> 24);
- bb[i+2] = (byte) (val >> 16);
- bb[i+1] = (byte) (val >> 8);
- bb[i+0] = (byte) (val >> 0);
-// if (false) {
-// String newVal = interpretLong(bb, i);
-// System.out.println("changed offset " + i + " from " + oldVal + " to " + newVal);
-// }
-
- }
-
- private static String interpretLong(byte[] fileContent, int offset) {
- InputStream is = new ByteArrayInputStream(fileContent, offset, 8);
- long l;
- try {
- l = new DataInputStream(is).readLong();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return "0x" + Long.toHexString(l).toUpperCase(Locale.ROOT);
- }
-
- private static boolean isNaNBytes(byte[] fileContent, int offset) {
- if(offset + JAVA_NAN_BYTES.length > fileContent.length) {
- return false;
- }
- // excel NaN bits: 0xFFFF0420003C0000L
- // java NaN bits :0x7ff8000000000000L
- return areArraySectionsEqual(fileContent, offset, JAVA_NAN_BYTES);
- }
- private static boolean areArraySectionsEqual(byte[] bb, int off, byte[] section) {
- for (int i=section.length-1; i>=0; i--) {
- if (bb[off+i] != section[i]){
- return false;
- }
- }
- return true;
- }
+ private final HSSFSheet _sheet;
+ private int _rowIndex;
+ private final List<Long> _replacementNaNs;
+
+ public SheetWriter(HSSFWorkbook wb) {
+ HSSFSheet sheet = wb.createSheet("Sheet1");
+
+ writeHeaderRow(wb, sheet);
+ _sheet = sheet;
+ _rowIndex = 1;
+ _replacementNaNs = new ArrayList<>();
+ }
+
+ void addTestRow(long rawBits, String expectedExcelRendering) {
+ writeDataRow(_sheet, _rowIndex++, rawBits, expectedExcelRendering);
+ if(Double.isNaN(Double.longBitsToDouble(rawBits))) {
+ _replacementNaNs.add(Long.valueOf(rawBits));
+ }
+ }
+
+ public long[] getReplacementNaNs() {
+ int nRepls = _replacementNaNs.size();
+ long[] result = new long[nRepls];
+ for (int i = 0; i < nRepls; i++) {
+ result[i] = _replacementNaNs.get(i).longValue();
+ }
+ return result;
+ }
+
+ }
+ /** 0x7ff8000000000000 encoded in little endian order */
+ private static final byte[] JAVA_NAN_BYTES = HexRead.readFromString("00 00 00 00 00 00 F8 7F");
+
+ private static void writeHeaderCell(HSSFRow row, int i, String text, HSSFCellStyle style) {
+ HSSFCell cell = row.createCell(i);
+ cell.setCellValue(new HSSFRichTextString(text));
+ cell.setCellStyle(style);
+ }
+ static void writeHeaderRow(HSSFWorkbook wb, HSSFSheet sheet) {
+ sheet.setColumnWidth(0, 3000);
+ sheet.setColumnWidth(1, 6000);
+ sheet.setColumnWidth(2, 6000);
+ sheet.setColumnWidth(3, 6000);
+ sheet.setColumnWidth(4, 6000);
+ sheet.setColumnWidth(5, 1600);
+ sheet.setColumnWidth(6, 20000);
+ HSSFRow row = sheet.createRow(0);
+ HSSFCellStyle style = wb.createCellStyle();
+ HSSFFont font = wb.createFont();
+ font.setBold(true);
+ style.setFont(font);
+ writeHeaderCell(row, 0, "Value", style);
+ writeHeaderCell(row, 1, "Raw Long Bits", style);
+ writeHeaderCell(row, 2, "JDK Double Rendering", style);
+ writeHeaderCell(row, 3, "Actual Rendering", style);
+ writeHeaderCell(row, 4, "Expected Rendering", style);
+ writeHeaderCell(row, 5, "Match", style);
+ writeHeaderCell(row, 6, "Java Metadata", style);
+ }
+ static void writeDataRow(HSSFSheet sheet, int rowIx, long rawLongBits, String expectedExcelRendering) {
+ double d = Double.longBitsToDouble(rawLongBits);
+ HSSFRow row = sheet.createRow(rowIx);
+
+ int rowNum = rowIx + 1;
+ String cel0ref = "A" + rowNum;
+ String rawBitsText = formatLongAsHex(rawLongBits);
+ String jmExpr = "'ec(" + rawBitsText + ", ''\" & C" + rowNum + " & \"'', ''\" & D" + rowNum + " & \"''),'";
+
+ // The 'Match' column will contain 'OK' if the metadata (from NumberToTextConversionExamples)
+ // matches Excel's rendering.
+ String matchExpr = "if(D" + rowNum + "=E" + rowNum + ", \"OK\", \"ERROR\")";
+
+ row.createCell(0).setCellValue(d);
+ row.createCell(1).setCellValue(new HSSFRichTextString(rawBitsText));
+ row.createCell(2).setCellValue(new HSSFRichTextString(Double.toString(d)));
+ row.createCell(3).setCellFormula("\"\" & " + cel0ref);
+ row.createCell(4).setCellValue(new HSSFRichTextString(expectedExcelRendering));
+ row.createCell(5).setCellFormula(matchExpr);
+ row.createCell(6).setCellFormula(jmExpr.replaceAll("'", "\""));
+
+// if (false) {
+// // for observing arithmetic near numeric range boundaries
+// row.createCell(7).setCellFormula(cel0ref + " * 1.0001");
+// row.createCell(8).setCellFormula(cel0ref + " / 1.0001");
+// }
+ }
+
+ private static String formatLongAsHex(long l) {
+ return HexDump.longToHex(l) + 'L';
+ }
+
+ public static void main(String[] args) {
+ writeJavaDoc();
+
+ HSSFWorkbook wb = new HSSFWorkbook();
+ SheetWriter sw = new SheetWriter(wb);
+
+ ExampleConversion[] exampleValues = NumberToTextConversionExamples.getExampleConversions();
+ for (ExampleConversion example : exampleValues) {
+ sw.addTestRow(example.getRawDoubleBits(), example.getExcelRendering());
+ }
+
+ File outputFile = new File("ExcelNumberRendering.xls");
+
+ try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream();
+ FileOutputStream os = new FileOutputStream(outputFile)) {
+ wb.write(baos);
+
+ byte[] fileContent = baos.toByteArray();
+ replaceNaNs(fileContent, sw.getReplacementNaNs());
+
+ os.write(fileContent);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ System.out.println("Finished writing '" + outputFile.getAbsolutePath() + "'");
+ }
+
+ public static void writeJavaDoc() {
+
+ ExampleConversion[] exampleConversions = NumberToTextConversionExamples.getExampleConversions();
+ for (ExampleConversion ec : exampleConversions) {
+ String line = " * <tr><td>"
+ + formatLongAsHex(ec.getRawDoubleBits())
+ + "</td><td>" + Double.toString(ec.getDoubleValue())
+ + "</td><td>" + ec.getExcelRendering() + "</td></tr>";
+
+ System.out.println(line);
+ }
+ }
+
+
+
+ private static void replaceNaNs(byte[] fileContent, long[] replacementNaNs) {
+ int countFound = 0;
+ for(int i=0; i<fileContent.length; i++) {
+ if(isNaNBytes(fileContent, i)) {
+ writeLong(fileContent, i, replacementNaNs[countFound]);
+ countFound++;
+ }
+ }
+ if (countFound < replacementNaNs.length) {
+ throw new RuntimeException("wrong repl count");
+ }
+
+ }
+
+ private static void writeLong(byte[] bb, int i, long val) {
+ /*String oldVal =*/ interpretLong(bb, i);
+ bb[i+7] = (byte) (val >> 56);
+ bb[i+6] = (byte) (val >> 48);
+ bb[i+5] = (byte) (val >> 40);
+ bb[i+4] = (byte) (val >> 32);
+ bb[i+3] = (byte) (val >> 24);
+ bb[i+2] = (byte) (val >> 16);
+ bb[i+1] = (byte) (val >> 8);
+ bb[i+0] = (byte) (val >> 0);
+// if (false) {
+// String newVal = interpretLong(bb, i);
+// System.out.println("changed offset " + i + " from " + oldVal + " to " + newVal);
+// }
+
+ }
+
+ private static String interpretLong(byte[] fileContent, int offset) {
+ InputStream is = new ByteArrayInputStream(fileContent, offset, 8);
+ long l;
+ try {
+ l = new DataInputStream(is).readLong();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return "0x" + Long.toHexString(l).toUpperCase(Locale.ROOT);
+ }
+
+ private static boolean isNaNBytes(byte[] fileContent, int offset) {
+ if(offset + JAVA_NAN_BYTES.length > fileContent.length) {
+ return false;
+ }
+ // excel NaN bits: 0xFFFF0420003C0000L
+ // java NaN bits :0x7ff8000000000000L
+ return areArraySectionsEqual(fileContent, offset, JAVA_NAN_BYTES);
+ }
+ private static boolean areArraySectionsEqual(byte[] bb, int off, byte[] section) {
+ for (int i=section.length-1; i>=0; i--) {
+ if (bb[off+i] != section[i]){
+ return false;
+ }
+ }
+ return true;
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberToTextConversionExamples.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberToTextConversionExamples.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberToTextConversionExamples.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/NumberToTextConversionExamples.java Sat May 22 20:56:44 2021
@@ -24,255 +24,255 @@ import java.util.Locale;
*/
final class NumberToTextConversionExamples {
- private NumberToTextConversionExamples() {
- // no instances of this class
- }
-
- public static final class ExampleConversion {
- private final String _javaRendering;
- private final String _excelRendering;
- private final double _doubleValue;
- private final long _rawDoubleBits;
-
- ExampleConversion(long rawDoubleBits, String javaRendering, String excelRendering) {
- double d = Double.longBitsToDouble(rawDoubleBits);
- if ("NaN".equals(javaRendering)) {
- if (!Double.isNaN(d)) {
- throw new IllegalArgumentException("value must be NaN");
- }
- } else {
- if (Double.isNaN(d)) {
- throw new IllegalArgumentException("value must not be NaN");
- }
- // just to be dead sure test conversion in java both ways
- boolean javaToStringOk = javaRendering.equals(Double.toString(d));
- boolean javaParseOk = Double.parseDouble(javaRendering) == d;
- if(!javaToStringOk || !javaParseOk) {
- String msgA = "Specified rawDoubleBits " + doubleToHexString(d) + " encodes to double '" + d + "'.";
- String msgB = "Specified javaRendering '" + javaRendering+ "' parses as double with rawDoubleBits "
- + doubleToHexString(Double.parseDouble(javaRendering));
- System.err.println(msgA);
- System.err.println(msgB);
-
- throw new RuntimeException(msgA + msgB);
- }
- }
- _rawDoubleBits = rawDoubleBits;
- _javaRendering = javaRendering;
- _excelRendering = excelRendering;
- _doubleValue = d;
- }
- private static String doubleToHexString(double d) {
- return "0x" + Long.toHexString(Double.doubleToLongBits(d)).toUpperCase(Locale.ROOT) + "L";
- }
- public String getJavaRendering() {
- return _javaRendering;
- }
- public String getExcelRendering() {
- return _excelRendering;
- }
- public double getDoubleValue() {
- return _doubleValue;
- }
- public boolean isNaN() {
- return Double.isNaN(_doubleValue);
- }
- public long getRawDoubleBits() {
- return _rawDoubleBits;
- }
- }
-
-
- /**
- * Number rendering examples as observed from Excel.
- * TODO - some are currently disabled because POI does not pass these cases yet
- */
- private static final ExampleConversion[] examples = {
-
- // basic numbers
- ec(0x0000000000000000L, "0.0", "0"),
- ec(0x3FF0000000000000L, "1.0", "1"),
- ec(0x3FF00068DB8BAC71L, "1.0001", "1.0001"),
- ec(0x4087A00000000000L, "756.0", "756"),
- ec(0x401E3D70A3D70A3DL, "7.56", "7.56"),
-
- ec(0x405EDD3C07FB4C8CL, "123.4567890123455", "123.456789012345"),
- ec(0x405EDD3C07FB4C99L, "123.45678901234568", "123.456789012346"),
- ec(0x405EDD3C07FB4CAEL, "123.45678901234598", "123.456789012346"),
- ec(0x4132D687E3DF2180L, "1234567.8901234567", "1234567.89012346"),
-
- ec(0x3F543A272D9E0E49L, "0.001234567890123455", "0.00123456789012345"),
- ec(0x3F543A272D9E0E4AL, "0.0012345678901234552", "0.00123456789012346"),
- ec(0x3F543A272D9E0E55L, "0.0012345678901234576", "0.00123456789012346"),
- ec(0x3F543A272D9E0E72L, "0.0012345678901234639", "0.00123456789012346"),
- ec(0x3F543A272D9E0E76L, "0.0012345678901234647", "0.00123456789012346"),
- ec(0x3F543A272D9E0E77L, "0.001234567890123465", "0.00123456789012346"),
-
- ec(0x3F543A272D9E0E78L, "0.0012345678901234652", "0.00123456789012347"),
-
- ec(0x3F543A272D9E0EA5L, "0.001234567890123475", "0.00123456789012347"),
- ec(0x3F543A272D9E0EA6L, "0.0012345678901234751", "0.00123456789012348"),
-
-
- ec(0x544CE6345CF3209CL, "1.2345678901234549E98", "1.23456789012345E+98"),
- ec(0x544CE6345CF3209DL, "1.234567890123455E98", "1.23456789012346E+98"),
- ec(0x544CE6345CF320DEL, "1.2345678901234649E98", "1.23456789012346E+98"),
- ec(0x544CE6345CF320DFL, "1.234567890123465E98", "1.23456789012347E+98"),
- ec(0x544CE6345CF32120L, "1.234567890123475E98", "1.23456789012347E+98"),
- ec(0x544CE6345CF32121L, "1.2345678901234751E98", "1.23456789012348E+98"),
-
-
- ec(0x54820FE0BA17F5E9L, "1.23456789012355E99", "1.2345678901236E+99"),
- ec(0x54820FE0BA17F5EAL, "1.2345678901235502E99", "1.2345678901236E+99"),
- ec(0x54820FE0BA17F784L, "1.2345678901236498E99", "1.2345678901237E+99"),
- ec(0x54820FE0BA17F785L, "1.23456789012365E99", "1.2345678901237E+99"),
- ec(0x54820FE0BA17F920L, "1.2345678901237498E99", "1.2345678901238E+99"),
- ec(0x54820FE0BA17F921L, "1.23456789012375E99", "1.2345678901238E+99"),
-
-
- // transitions around the E98,E99,E100 boundaries
- ec(0x547D42AEA2879F19L,"9.999999999999974E98", "9.99999999999997E+98"),
- ec(0x547D42AEA2879F1AL,"9.999999999999975E98", "9.99999999999998E+98"),
- ec(0x547D42AEA2879F21L,"9.999999999999984E98", "9.99999999999998E+98"),
- ec(0x547D42AEA2879F22L,"9.999999999999985E98", "9.99999999999999E+98"),
- ec(0x547D42AEA2879F2AL,"9.999999999999995E98", "9.99999999999999E+98"),
- ec(0x547D42AEA2879F2BL,"9.999999999999996E98", "1E+99"),
- ec(0x547D42AEA287A0A0L,"1.0000000000000449E99", "1E+99"),
- ec(0x547D42AEA287A0A1L,"1.000000000000045E99", "1.0000000000001E+99"),
- ec(0x547D42AEA287A3D8L,"1.0000000000001449E99", "1.0000000000001E+99"),
- ec(0x547D42AEA287A3D9L,"1.000000000000145E99", "1.0000000000002E+99"),
- ec(0x547D42AEA287A710L,"1.000000000000245E99", "1.0000000000002E+99"),
- ec(0x547D42AEA287A711L,"1.0000000000002451E99", "1.0000000000003E+99"),
-
-
- ec(0x54B249AD2594C2F9L,"9.999999999999744E99", "9.9999999999997E+99"),
- ec(0x54B249AD2594C2FAL,"9.999999999999746E99", "9.9999999999998E+99"),
- ec(0x54B249AD2594C32DL,"9.999999999999845E99", "9.9999999999998E+99"),
- ec(0x54B249AD2594C32EL,"9.999999999999847E99", "9.9999999999999E+99"),
- ec(0x54B249AD2594C360L,"9.999999999999944E99", "9.9999999999999E+99"),
- ec(0x54B249AD2594C361L,"9.999999999999946E99", "1E+100"),
- ec(0x54B249AD2594C464L,"1.0000000000000449E100","1E+100"),
- ec(0x54B249AD2594C465L,"1.000000000000045E100", "1.0000000000001E+100"),
- ec(0x54B249AD2594C667L,"1.000000000000145E100", "1.0000000000001E+100"),
- ec(0x54B249AD2594C668L,"1.0000000000001451E100","1.0000000000002E+100"),
- ec(0x54B249AD2594C86AL,"1.000000000000245E100", "1.0000000000002E+100"),
- ec(0x54B249AD2594C86BL,"1.0000000000002452E100","1.0000000000003E+100"),
-
-
- ec(0x2B95DF5CA28EF4A8L,"1.0000000000000251E-98","1.00000000000003E-98"),
- ec(0x2B95DF5CA28EF4A7L,"1.000000000000025E-98", "1.00000000000002E-98"),
- ec(0x2B95DF5CA28EF46AL,"1.000000000000015E-98", "1.00000000000002E-98"),
- ec(0x2B95DF5CA28EF469L,"1.0000000000000149E-98","1.00000000000001E-98"),
- ec(0x2B95DF5CA28EF42DL,"1.0000000000000051E-98","1.00000000000001E-98"),
- ec(0x2B95DF5CA28EF42CL,"1.000000000000005E-98", "1E-98"),
- ec(0x2B95DF5CA28EF3ECL,"9.999999999999946E-99", "1E-98"),
- ec(0x2B95DF5CA28EF3EBL,"9.999999999999944E-99", "9.9999999999999E-99"),
- ec(0x2B95DF5CA28EF3AEL,"9.999999999999845E-99", "9.9999999999999E-99"),
- ec(0x2B95DF5CA28EF3ADL,"9.999999999999843E-99", "9.9999999999998E-99"),
- ec(0x2B95DF5CA28EF371L,"9.999999999999746E-99", "9.9999999999998E-99"),
- ec(0x2B95DF5CA28EF370L,"9.999999999999744E-99", "9.9999999999997E-99"),
-
-
- ec(0x2B617F7D4ED8C7F5L,"1.000000000000245E-99", "1.0000000000003E-99"),
- ec(0x2B617F7D4ED8C7F4L,"1.0000000000002449E-99","1.0000000000002E-99"),
- ec(0x2B617F7D4ED8C609L,"1.0000000000001452E-99","1.0000000000002E-99"),
- ec(0x2B617F7D4ED8C608L,"1.000000000000145E-99", "1.0000000000001E-99"),
- ec(0x2B617F7D4ED8C41CL,"1.000000000000045E-99", "1.0000000000001E-99"),
- ec(0x2B617F7D4ED8C41BL,"1.0000000000000449E-99","1E-99"),
- ec(0x2B617F7D4ED8C323L,"9.999999999999945E-100","1E-99"),
- ec(0x2B617F7D4ED8C322L,"9.999999999999943E-100","9.9999999999999E-100"),
- ec(0x2B617F7D4ED8C2F2L,"9.999999999999846E-100","9.9999999999999E-100"),
- ec(0x2B617F7D4ED8C2F1L,"9.999999999999844E-100","9.9999999999998E-100"),
- ec(0x2B617F7D4ED8C2C1L,"9.999999999999746E-100","9.9999999999998E-100"),
- ec(0x2B617F7D4ED8C2C0L,"9.999999999999744E-100","9.9999999999997E-100"),
-
-
-
- // small numbers
- ec(0x3EE9E409302678BAL, "1.2345678901234568E-5", "1.23456789012346E-05"),
- ec(0x3F202E85BE180B74L, "1.2345678901234567E-4", "0.000123456789012346"),
- ec(0x3F543A272D9E0E51L, "0.0012345678901234567", "0.00123456789012346"),
- ec(0x3F8948B0F90591E6L, "0.012345678901234568", "0.0123456789012346"),
-
- ec(0x3EE9E409301B5A02L, "1.23456789E-5", "0.0000123456789"),
-
- ec(0x3E6E7D05BDABDE50L, "5.6789012345E-8", "0.000000056789012345"),
- ec(0x3E6E7D05BDAD407EL, "5.67890123456E-8", "5.67890123456E-08"),
- ec(0x3E6E7D06029F18BEL, "5.678902E-8", "0.00000005678902"),
-
- ec(0x2BCB5733CB32AE6EL, "9.999999999999123E-98", "9.99999999999912E-98"),
- ec(0x2B617F7D4ED8C59EL, "1.0000000000001235E-99", "1.0000000000001E-99"),
- ec(0x0036319916D67853L, "1.2345678901234578E-307", "1.2345678901235E-307"),
-
- ec(0x359DEE7A4AD4B81FL, "2.0E-50", "2E-50"),
-
- // large numbers
- ec(0x41678C29DCD6E9E0L, "1.2345678901234567E7", "12345678.9012346"),
- ec(0x42A674E79C5FE523L, "1.2345678901234568E13", "12345678901234.6"),
- ec(0x42DC12218377DE6BL, "1.2345678901234567E14", "123456789012346"),
- ec(0x43118B54F22AEB03L, "1.2345678901234568E15", "1234567890123460"),
- ec(0x43E56A95319D63E1L, "1.2345678901234567E19", "12345678901234600000"),
- ec(0x441AC53A7E04BCDAL, "1.2345678901234568E20", "1.23456789012346E+20"),
- ec(0xC3E56A95319D63E1L, "-1.2345678901234567E19", "-12345678901234600000"),
- ec(0xC41AC53A7E04BCDAL, "-1.2345678901234568E20", "-1.23456789012346E+20"),
-
- ec(0x54820FE0BA17F46DL, "1.2345678901234577E99", "1.2345678901235E+99"),
- ec(0x54B693D8E89DF188L, "1.2345678901234576E100", "1.2345678901235E+100"),
-
- ec(0x4A611B0EC57E649AL, "2.0E50", "2E+50"),
-
- // range extremities
- ec(0x7FEFFFFFFFFFFFFFL, "1.7976931348623157E308", "1.7976931348623E+308"),
- ec(0x0010000000000000L, "2.2250738585072014E-308", "2.2250738585072E-308"),
- ec(0x000FFFFFFFFFFFFFL, "2.225073858507201E-308", "0"),
- ec(0x0000000000000001L, "4.9E-324", "0"),
-
- // infinity
- ec(0x7FF0000000000000L, "Infinity", "1.7976931348623E+308"),
- ec(0xFFF0000000000000L, "-Infinity", "1.7976931348623E+308"),
-
- // shortening due to rounding
- ec(0x441AC7A08EAD02F2L, "1.234999999999999E20", "1.235E+20"),
- ec(0x40FE26BFFFFFFFF9L, "123499.9999999999", "123500"),
- ec(0x3E4A857BFB2F2809L, "1.234999999999999E-8", "0.00000001235"),
- ec(0x3BCD291DEF868C89L, "1.234999999999999E-20", "1.235E-20"),
-
- // carry up due to rounding
- // For clarity these tests choose values that don't round in java,
- // but will round in excel. In some cases there is almost no difference
- // between excel and java (e.g. 9.9..9E-8)
- ec(0x444B1AE4D6E2EF4FL, "9.999999999999999E20", "1E+21"),
- ec(0x412E847FFFFFFFFFL, "999999.9999999999", "1000000"),
- ec(0x3E45798EE2308C39L, "9.999999999999999E-9", "0.00000001"),
- ec(0x3C32725DD1D243ABL, "9.999999999999999E-19", "0.000000000000000001"),
- ec(0x3BFD83C94FB6D2ABL, "9.999999999999999E-20", "1E-19"),
-
- ec(0xC44B1AE4D6E2EF4FL, "-9.999999999999999E20", "-1E+21"),
- ec(0xC12E847FFFFFFFFFL, "-999999.9999999999", "-1000000"),
- ec(0xBE45798EE2308C39L, "-9.999999999999999E-9", "-0.00000001"),
- ec(0xBC32725DD1D243ABL, "-9.999999999999999E-19", "-0.000000000000000001"),
- ec(0xBBFD83C94FB6D2ABL, "-9.999999999999999E-20", "-1E-19"),
-
-
- // NaNs
- // Currently these test cases are not critical, since other limitations prevent any variety in
- // or control of the bit patterns used to encode NaNs in evaluations.
- ec(0xFFFF0420003C0000L, "NaN", "3.484840871308E+308"),
- ec(0x7FF8000000000000L, "NaN", "2.6965397022935E+308"),
- ec(0x7FFF0420003C0000L, "NaN", "3.484840871308E+308"),
- ec(0xFFF8000000000000L, "NaN", "2.6965397022935E+308"),
- ec(0xFFFF0AAAAAAAAAAAL, "NaN", "3.4877119413344E+308"),
- ec(0x7FF80AAAAAAAAAAAL, "NaN", "2.7012211948322E+308"),
- ec(0xFFFFFFFFFFFFFFFFL, "NaN", "3.5953862697246E+308"),
- ec(0x7FFFFFFFFFFFFFFFL, "NaN", "3.5953862697246E+308"),
- ec(0xFFF7FFFFFFFFFFFFL, "NaN", "2.6965397022935E+308"),
- };
-
- private static ExampleConversion ec(long rawDoubleBits, String javaRendering, String excelRendering) {
- return new ExampleConversion(rawDoubleBits, javaRendering, excelRendering);
- }
-
- public static ExampleConversion[] getExampleConversions() {
- return examples.clone();
- }
+ private NumberToTextConversionExamples() {
+ // no instances of this class
+ }
+
+ public static final class ExampleConversion {
+ private final String _javaRendering;
+ private final String _excelRendering;
+ private final double _doubleValue;
+ private final long _rawDoubleBits;
+
+ ExampleConversion(long rawDoubleBits, String javaRendering, String excelRendering) {
+ double d = Double.longBitsToDouble(rawDoubleBits);
+ if ("NaN".equals(javaRendering)) {
+ if (!Double.isNaN(d)) {
+ throw new IllegalArgumentException("value must be NaN");
+ }
+ } else {
+ if (Double.isNaN(d)) {
+ throw new IllegalArgumentException("value must not be NaN");
+ }
+ // just to be dead sure test conversion in java both ways
+ boolean javaToStringOk = javaRendering.equals(Double.toString(d));
+ boolean javaParseOk = Double.parseDouble(javaRendering) == d;
+ if(!javaToStringOk || !javaParseOk) {
+ String msgA = "Specified rawDoubleBits " + doubleToHexString(d) + " encodes to double '" + d + "'.";
+ String msgB = "Specified javaRendering '" + javaRendering+ "' parses as double with rawDoubleBits "
+ + doubleToHexString(Double.parseDouble(javaRendering));
+ System.err.println(msgA);
+ System.err.println(msgB);
+
+ throw new RuntimeException(msgA + msgB);
+ }
+ }
+ _rawDoubleBits = rawDoubleBits;
+ _javaRendering = javaRendering;
+ _excelRendering = excelRendering;
+ _doubleValue = d;
+ }
+ private static String doubleToHexString(double d) {
+ return "0x" + Long.toHexString(Double.doubleToLongBits(d)).toUpperCase(Locale.ROOT) + "L";
+ }
+ public String getJavaRendering() {
+ return _javaRendering;
+ }
+ public String getExcelRendering() {
+ return _excelRendering;
+ }
+ public double getDoubleValue() {
+ return _doubleValue;
+ }
+ public boolean isNaN() {
+ return Double.isNaN(_doubleValue);
+ }
+ public long getRawDoubleBits() {
+ return _rawDoubleBits;
+ }
+ }
+
+
+ /**
+ * Number rendering examples as observed from Excel.
+ * TODO - some are currently disabled because POI does not pass these cases yet
+ */
+ private static final ExampleConversion[] examples = {
+
+ // basic numbers
+ ec(0x0000000000000000L, "0.0", "0"),
+ ec(0x3FF0000000000000L, "1.0", "1"),
+ ec(0x3FF00068DB8BAC71L, "1.0001", "1.0001"),
+ ec(0x4087A00000000000L, "756.0", "756"),
+ ec(0x401E3D70A3D70A3DL, "7.56", "7.56"),
+
+ ec(0x405EDD3C07FB4C8CL, "123.4567890123455", "123.456789012345"),
+ ec(0x405EDD3C07FB4C99L, "123.45678901234568", "123.456789012346"),
+ ec(0x405EDD3C07FB4CAEL, "123.45678901234598", "123.456789012346"),
+ ec(0x4132D687E3DF2180L, "1234567.8901234567", "1234567.89012346"),
+
+ ec(0x3F543A272D9E0E49L, "0.001234567890123455", "0.00123456789012345"),
+ ec(0x3F543A272D9E0E4AL, "0.0012345678901234552", "0.00123456789012346"),
+ ec(0x3F543A272D9E0E55L, "0.0012345678901234576", "0.00123456789012346"),
+ ec(0x3F543A272D9E0E72L, "0.0012345678901234639", "0.00123456789012346"),
+ ec(0x3F543A272D9E0E76L, "0.0012345678901234647", "0.00123456789012346"),
+ ec(0x3F543A272D9E0E77L, "0.001234567890123465", "0.00123456789012346"),
+
+ ec(0x3F543A272D9E0E78L, "0.0012345678901234652", "0.00123456789012347"),
+
+ ec(0x3F543A272D9E0EA5L, "0.001234567890123475", "0.00123456789012347"),
+ ec(0x3F543A272D9E0EA6L, "0.0012345678901234751", "0.00123456789012348"),
+
+
+ ec(0x544CE6345CF3209CL, "1.2345678901234549E98", "1.23456789012345E+98"),
+ ec(0x544CE6345CF3209DL, "1.234567890123455E98", "1.23456789012346E+98"),
+ ec(0x544CE6345CF320DEL, "1.2345678901234649E98", "1.23456789012346E+98"),
+ ec(0x544CE6345CF320DFL, "1.234567890123465E98", "1.23456789012347E+98"),
+ ec(0x544CE6345CF32120L, "1.234567890123475E98", "1.23456789012347E+98"),
+ ec(0x544CE6345CF32121L, "1.2345678901234751E98", "1.23456789012348E+98"),
+
+
+ ec(0x54820FE0BA17F5E9L, "1.23456789012355E99", "1.2345678901236E+99"),
+ ec(0x54820FE0BA17F5EAL, "1.2345678901235502E99", "1.2345678901236E+99"),
+ ec(0x54820FE0BA17F784L, "1.2345678901236498E99", "1.2345678901237E+99"),
+ ec(0x54820FE0BA17F785L, "1.23456789012365E99", "1.2345678901237E+99"),
+ ec(0x54820FE0BA17F920L, "1.2345678901237498E99", "1.2345678901238E+99"),
+ ec(0x54820FE0BA17F921L, "1.23456789012375E99", "1.2345678901238E+99"),
+
+
+ // transitions around the E98,E99,E100 boundaries
+ ec(0x547D42AEA2879F19L,"9.999999999999974E98", "9.99999999999997E+98"),
+ ec(0x547D42AEA2879F1AL,"9.999999999999975E98", "9.99999999999998E+98"),
+ ec(0x547D42AEA2879F21L,"9.999999999999984E98", "9.99999999999998E+98"),
+ ec(0x547D42AEA2879F22L,"9.999999999999985E98", "9.99999999999999E+98"),
+ ec(0x547D42AEA2879F2AL,"9.999999999999995E98", "9.99999999999999E+98"),
+ ec(0x547D42AEA2879F2BL,"9.999999999999996E98", "1E+99"),
+ ec(0x547D42AEA287A0A0L,"1.0000000000000449E99", "1E+99"),
+ ec(0x547D42AEA287A0A1L,"1.000000000000045E99", "1.0000000000001E+99"),
+ ec(0x547D42AEA287A3D8L,"1.0000000000001449E99", "1.0000000000001E+99"),
+ ec(0x547D42AEA287A3D9L,"1.000000000000145E99", "1.0000000000002E+99"),
+ ec(0x547D42AEA287A710L,"1.000000000000245E99", "1.0000000000002E+99"),
+ ec(0x547D42AEA287A711L,"1.0000000000002451E99", "1.0000000000003E+99"),
+
+
+ ec(0x54B249AD2594C2F9L,"9.999999999999744E99", "9.9999999999997E+99"),
+ ec(0x54B249AD2594C2FAL,"9.999999999999746E99", "9.9999999999998E+99"),
+ ec(0x54B249AD2594C32DL,"9.999999999999845E99", "9.9999999999998E+99"),
+ ec(0x54B249AD2594C32EL,"9.999999999999847E99", "9.9999999999999E+99"),
+ ec(0x54B249AD2594C360L,"9.999999999999944E99", "9.9999999999999E+99"),
+ ec(0x54B249AD2594C361L,"9.999999999999946E99", "1E+100"),
+ ec(0x54B249AD2594C464L,"1.0000000000000449E100","1E+100"),
+ ec(0x54B249AD2594C465L,"1.000000000000045E100", "1.0000000000001E+100"),
+ ec(0x54B249AD2594C667L,"1.000000000000145E100", "1.0000000000001E+100"),
+ ec(0x54B249AD2594C668L,"1.0000000000001451E100","1.0000000000002E+100"),
+ ec(0x54B249AD2594C86AL,"1.000000000000245E100", "1.0000000000002E+100"),
+ ec(0x54B249AD2594C86BL,"1.0000000000002452E100","1.0000000000003E+100"),
+
+
+ ec(0x2B95DF5CA28EF4A8L,"1.0000000000000251E-98","1.00000000000003E-98"),
+ ec(0x2B95DF5CA28EF4A7L,"1.000000000000025E-98", "1.00000000000002E-98"),
+ ec(0x2B95DF5CA28EF46AL,"1.000000000000015E-98", "1.00000000000002E-98"),
+ ec(0x2B95DF5CA28EF469L,"1.0000000000000149E-98","1.00000000000001E-98"),
+ ec(0x2B95DF5CA28EF42DL,"1.0000000000000051E-98","1.00000000000001E-98"),
+ ec(0x2B95DF5CA28EF42CL,"1.000000000000005E-98", "1E-98"),
+ ec(0x2B95DF5CA28EF3ECL,"9.999999999999946E-99", "1E-98"),
+ ec(0x2B95DF5CA28EF3EBL,"9.999999999999944E-99", "9.9999999999999E-99"),
+ ec(0x2B95DF5CA28EF3AEL,"9.999999999999845E-99", "9.9999999999999E-99"),
+ ec(0x2B95DF5CA28EF3ADL,"9.999999999999843E-99", "9.9999999999998E-99"),
+ ec(0x2B95DF5CA28EF371L,"9.999999999999746E-99", "9.9999999999998E-99"),
+ ec(0x2B95DF5CA28EF370L,"9.999999999999744E-99", "9.9999999999997E-99"),
+
+
+ ec(0x2B617F7D4ED8C7F5L,"1.000000000000245E-99", "1.0000000000003E-99"),
+ ec(0x2B617F7D4ED8C7F4L,"1.0000000000002449E-99","1.0000000000002E-99"),
+ ec(0x2B617F7D4ED8C609L,"1.0000000000001452E-99","1.0000000000002E-99"),
+ ec(0x2B617F7D4ED8C608L,"1.000000000000145E-99", "1.0000000000001E-99"),
+ ec(0x2B617F7D4ED8C41CL,"1.000000000000045E-99", "1.0000000000001E-99"),
+ ec(0x2B617F7D4ED8C41BL,"1.0000000000000449E-99","1E-99"),
+ ec(0x2B617F7D4ED8C323L,"9.999999999999945E-100","1E-99"),
+ ec(0x2B617F7D4ED8C322L,"9.999999999999943E-100","9.9999999999999E-100"),
+ ec(0x2B617F7D4ED8C2F2L,"9.999999999999846E-100","9.9999999999999E-100"),
+ ec(0x2B617F7D4ED8C2F1L,"9.999999999999844E-100","9.9999999999998E-100"),
+ ec(0x2B617F7D4ED8C2C1L,"9.999999999999746E-100","9.9999999999998E-100"),
+ ec(0x2B617F7D4ED8C2C0L,"9.999999999999744E-100","9.9999999999997E-100"),
+
+
+
+ // small numbers
+ ec(0x3EE9E409302678BAL, "1.2345678901234568E-5", "1.23456789012346E-05"),
+ ec(0x3F202E85BE180B74L, "1.2345678901234567E-4", "0.000123456789012346"),
+ ec(0x3F543A272D9E0E51L, "0.0012345678901234567", "0.00123456789012346"),
+ ec(0x3F8948B0F90591E6L, "0.012345678901234568", "0.0123456789012346"),
+
+ ec(0x3EE9E409301B5A02L, "1.23456789E-5", "0.0000123456789"),
+
+ ec(0x3E6E7D05BDABDE50L, "5.6789012345E-8", "0.000000056789012345"),
+ ec(0x3E6E7D05BDAD407EL, "5.67890123456E-8", "5.67890123456E-08"),
+ ec(0x3E6E7D06029F18BEL, "5.678902E-8", "0.00000005678902"),
+
+ ec(0x2BCB5733CB32AE6EL, "9.999999999999123E-98", "9.99999999999912E-98"),
+ ec(0x2B617F7D4ED8C59EL, "1.0000000000001235E-99", "1.0000000000001E-99"),
+ ec(0x0036319916D67853L, "1.2345678901234578E-307", "1.2345678901235E-307"),
+
+ ec(0x359DEE7A4AD4B81FL, "2.0E-50", "2E-50"),
+
+ // large numbers
+ ec(0x41678C29DCD6E9E0L, "1.2345678901234567E7", "12345678.9012346"),
+ ec(0x42A674E79C5FE523L, "1.2345678901234568E13", "12345678901234.6"),
+ ec(0x42DC12218377DE6BL, "1.2345678901234567E14", "123456789012346"),
+ ec(0x43118B54F22AEB03L, "1.2345678901234568E15", "1234567890123460"),
+ ec(0x43E56A95319D63E1L, "1.2345678901234567E19", "12345678901234600000"),
+ ec(0x441AC53A7E04BCDAL, "1.2345678901234568E20", "1.23456789012346E+20"),
+ ec(0xC3E56A95319D63E1L, "-1.2345678901234567E19", "-12345678901234600000"),
+ ec(0xC41AC53A7E04BCDAL, "-1.2345678901234568E20", "-1.23456789012346E+20"),
+
+ ec(0x54820FE0BA17F46DL, "1.2345678901234577E99", "1.2345678901235E+99"),
+ ec(0x54B693D8E89DF188L, "1.2345678901234576E100", "1.2345678901235E+100"),
+
+ ec(0x4A611B0EC57E649AL, "2.0E50", "2E+50"),
+
+ // range extremities
+ ec(0x7FEFFFFFFFFFFFFFL, "1.7976931348623157E308", "1.7976931348623E+308"),
+ ec(0x0010000000000000L, "2.2250738585072014E-308", "2.2250738585072E-308"),
+ ec(0x000FFFFFFFFFFFFFL, "2.225073858507201E-308", "0"),
+ ec(0x0000000000000001L, "4.9E-324", "0"),
+
+ // infinity
+ ec(0x7FF0000000000000L, "Infinity", "1.7976931348623E+308"),
+ ec(0xFFF0000000000000L, "-Infinity", "1.7976931348623E+308"),
+
+ // shortening due to rounding
+ ec(0x441AC7A08EAD02F2L, "1.234999999999999E20", "1.235E+20"),
+ ec(0x40FE26BFFFFFFFF9L, "123499.9999999999", "123500"),
+ ec(0x3E4A857BFB2F2809L, "1.234999999999999E-8", "0.00000001235"),
+ ec(0x3BCD291DEF868C89L, "1.234999999999999E-20", "1.235E-20"),
+
+ // carry up due to rounding
+ // For clarity these tests choose values that don't round in java,
+ // but will round in excel. In some cases there is almost no difference
+ // between excel and java (e.g. 9.9..9E-8)
+ ec(0x444B1AE4D6E2EF4FL, "9.999999999999999E20", "1E+21"),
+ ec(0x412E847FFFFFFFFFL, "999999.9999999999", "1000000"),
+ ec(0x3E45798EE2308C39L, "9.999999999999999E-9", "0.00000001"),
+ ec(0x3C32725DD1D243ABL, "9.999999999999999E-19", "0.000000000000000001"),
+ ec(0x3BFD83C94FB6D2ABL, "9.999999999999999E-20", "1E-19"),
+
+ ec(0xC44B1AE4D6E2EF4FL, "-9.999999999999999E20", "-1E+21"),
+ ec(0xC12E847FFFFFFFFFL, "-999999.9999999999", "-1000000"),
+ ec(0xBE45798EE2308C39L, "-9.999999999999999E-9", "-0.00000001"),
+ ec(0xBC32725DD1D243ABL, "-9.999999999999999E-19", "-0.000000000000000001"),
+ ec(0xBBFD83C94FB6D2ABL, "-9.999999999999999E-20", "-1E-19"),
+
+
+ // NaNs
+ // Currently these test cases are not critical, since other limitations prevent any variety in
+ // or control of the bit patterns used to encode NaNs in evaluations.
+ ec(0xFFFF0420003C0000L, "NaN", "3.484840871308E+308"),
+ ec(0x7FF8000000000000L, "NaN", "2.6965397022935E+308"),
+ ec(0x7FFF0420003C0000L, "NaN", "3.484840871308E+308"),
+ ec(0xFFF8000000000000L, "NaN", "2.6965397022935E+308"),
+ ec(0xFFFF0AAAAAAAAAAAL, "NaN", "3.4877119413344E+308"),
+ ec(0x7FF80AAAAAAAAAAAL, "NaN", "2.7012211948322E+308"),
+ ec(0xFFFFFFFFFFFFFFFFL, "NaN", "3.5953862697246E+308"),
+ ec(0x7FFFFFFFFFFFFFFFL, "NaN", "3.5953862697246E+308"),
+ ec(0xFFF7FFFFFFFFFFFFL, "NaN", "2.6965397022935E+308"),
+ };
+
+ private static ExampleConversion ec(long rawDoubleBits, String javaRendering, String excelRendering) {
+ return new ExampleConversion(rawDoubleBits, javaRendering, excelRendering);
+ }
+
+ public static ExampleConversion[] getExampleConversions() {
+ return examples.clone();
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestExpandedDouble.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestExpandedDouble.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestExpandedDouble.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestExpandedDouble.java Sat May 22 20:56:44 2021
@@ -31,98 +31,98 @@ import org.junit.jupiter.params.provider
* Tests for {@link ExpandedDouble}
*/
final class TestExpandedDouble {
- private static final BigInteger BIG_POW_10 = BigInteger.valueOf(1000000000);
+ private static final BigInteger BIG_POW_10 = BigInteger.valueOf(1000000000);
- @Test
- void testNegative() {
- ExpandedDouble hd = new ExpandedDouble(0xC010000000000000L);
- assertNotEquals(-2046, hd.getBinaryExponent(), "identified bug - sign bit not masked out of exponent");
- assertEquals(2, hd.getBinaryExponent());
- BigInteger frac = hd.getSignificand();
- assertEquals(64, frac.bitLength());
- assertEquals(1, frac.bitCount());
- }
-
- @Test
- void testSubnormal() {
- ExpandedDouble hd = new ExpandedDouble(0x0000000000000001L);
- assertNotEquals(-1023, hd.getBinaryExponent(), "identified bug - subnormal numbers not decoded properly");
- assertEquals(-1086, hd.getBinaryExponent());
- BigInteger frac = hd.getSignificand();
- assertEquals(64, frac.bitLength());
- assertEquals(1, frac.bitCount());
- }
-
- /**
- * Tests specific values for conversion from {@link ExpandedDouble} to {@link NormalisedDecimal} and back
- */
- @ParameterizedTest
- @ValueSource(longs = {
- 0x4010000000000004L,
- 0x7010000000000004L,
- 0x1010000000000004L,
- 0x0010000000000001L, // near lowest normal number
- 0x0010000000000000L, // lowest normal number
- 0x000FFFFFFFFFFFFFL, // highest subnormal number
- 0x0008000000000000L, // subnormal number
-
- 0xC010000000000004L,
- 0xE230100010001004L,
- 0x403CE0FFFFFFFFF2L,
- 0x0000000000000001L, // smallest non-zero number (subnormal)
- 0x6230100010000FFEL,
- 0x6230100010000FFFL,
- 0x6230100010001000L,
- 0x403CE0FFFFFFFFF0L, // has single digit round trip error
- 0x2B2BFFFF10001079L,
- })
- void confirmRoundTrip(long rawBitsA) {
- double a = Double.longBitsToDouble(rawBitsA);
- if (a == 0.0) {
- // Can't represent 0.0 or -0.0 with NormalisedDecimal
- return;
- }
- ExpandedDouble ed1 = new ExpandedDouble(rawBitsA);
- NormalisedDecimal nd2 = ed1.normaliseBaseTen();
- checkNormaliseBaseTenResult(ed1, nd2);
-
- ExpandedDouble ed3 = nd2.normaliseBaseTwo();
- assertEquals(ed3.getBinaryExponent(), ed1.getBinaryExponent(), "bin exp mismatch");
-
- BigInteger diff = ed3.getSignificand().subtract(ed1.getSignificand()).abs();
- if (diff.signum() == 0) {
- return;
- }
- // original quantity only has 53 bits of precision
- // these quantities may have errors in the 64th bit, which hopefully don't make any difference
-
- // errors in the 64th bit happen from time to time
- // this is well below the 53 bits of precision required
- assertTrue(diff.bitLength() < 2);
- }
-
-
- private static void checkNormaliseBaseTenResult(ExpandedDouble orig, NormalisedDecimal result) {
- String sigDigs = result.getSignificantDecimalDigits();
- BigInteger frac = orig.getSignificand();
- while (frac.bitLength() + orig.getBinaryExponent() < 200) {
- frac = frac.multiply(BIG_POW_10);
- }
- int binaryExp = orig.getBinaryExponent() - orig.getSignificand().bitLength();
-
- String origDigs = frac.shiftLeft(binaryExp+1).toString(10);
- assertTrue(origDigs.startsWith(sigDigs));
-
- double dO = Double.parseDouble("0." + origDigs.substring(sigDigs.length()));
- double d1 = Double.parseDouble(result.getFractionalPart().toPlainString());
- BigInteger subDigsO = BigInteger.valueOf((int) (dO * 32768 + 0.5));
- BigInteger subDigsB = BigInteger.valueOf((int) (d1 * 32768 + 0.5));
-
- if (subDigsO.equals(subDigsB)) {
- return;
- }
- BigInteger diff = subDigsB.subtract(subDigsO).abs();
- // 100/32768 ~= 0.003
- assertTrue(diff.intValue() <= 100, "minor mistake");
- }
+ @Test
+ void testNegative() {
+ ExpandedDouble hd = new ExpandedDouble(0xC010000000000000L);
+ assertNotEquals(-2046, hd.getBinaryExponent(), "identified bug - sign bit not masked out of exponent");
+ assertEquals(2, hd.getBinaryExponent());
+ BigInteger frac = hd.getSignificand();
+ assertEquals(64, frac.bitLength());
+ assertEquals(1, frac.bitCount());
+ }
+
+ @Test
+ void testSubnormal() {
+ ExpandedDouble hd = new ExpandedDouble(0x0000000000000001L);
+ assertNotEquals(-1023, hd.getBinaryExponent(), "identified bug - subnormal numbers not decoded properly");
+ assertEquals(-1086, hd.getBinaryExponent());
+ BigInteger frac = hd.getSignificand();
+ assertEquals(64, frac.bitLength());
+ assertEquals(1, frac.bitCount());
+ }
+
+ /**
+ * Tests specific values for conversion from {@link ExpandedDouble} to {@link NormalisedDecimal} and back
+ */
+ @ParameterizedTest
+ @ValueSource(longs = {
+ 0x4010000000000004L,
+ 0x7010000000000004L,
+ 0x1010000000000004L,
+ 0x0010000000000001L, // near lowest normal number
+ 0x0010000000000000L, // lowest normal number
+ 0x000FFFFFFFFFFFFFL, // highest subnormal number
+ 0x0008000000000000L, // subnormal number
+
+ 0xC010000000000004L,
+ 0xE230100010001004L,
+ 0x403CE0FFFFFFFFF2L,
+ 0x0000000000000001L, // smallest non-zero number (subnormal)
+ 0x6230100010000FFEL,
+ 0x6230100010000FFFL,
+ 0x6230100010001000L,
+ 0x403CE0FFFFFFFFF0L, // has single digit round trip error
+ 0x2B2BFFFF10001079L,
+ })
+ void confirmRoundTrip(long rawBitsA) {
+ double a = Double.longBitsToDouble(rawBitsA);
+ if (a == 0.0) {
+ // Can't represent 0.0 or -0.0 with NormalisedDecimal
+ return;
+ }
+ ExpandedDouble ed1 = new ExpandedDouble(rawBitsA);
+ NormalisedDecimal nd2 = ed1.normaliseBaseTen();
+ checkNormaliseBaseTenResult(ed1, nd2);
+
+ ExpandedDouble ed3 = nd2.normaliseBaseTwo();
+ assertEquals(ed3.getBinaryExponent(), ed1.getBinaryExponent(), "bin exp mismatch");
+
+ BigInteger diff = ed3.getSignificand().subtract(ed1.getSignificand()).abs();
+ if (diff.signum() == 0) {
+ return;
+ }
+ // original quantity only has 53 bits of precision
+ // these quantities may have errors in the 64th bit, which hopefully don't make any difference
+
+ // errors in the 64th bit happen from time to time
+ // this is well below the 53 bits of precision required
+ assertTrue(diff.bitLength() < 2);
+ }
+
+
+ private static void checkNormaliseBaseTenResult(ExpandedDouble orig, NormalisedDecimal result) {
+ String sigDigs = result.getSignificantDecimalDigits();
+ BigInteger frac = orig.getSignificand();
+ while (frac.bitLength() + orig.getBinaryExponent() < 200) {
+ frac = frac.multiply(BIG_POW_10);
+ }
+ int binaryExp = orig.getBinaryExponent() - orig.getSignificand().bitLength();
+
+ String origDigs = frac.shiftLeft(binaryExp+1).toString(10);
+ assertTrue(origDigs.startsWith(sigDigs));
+
+ double dO = Double.parseDouble("0." + origDigs.substring(sigDigs.length()));
+ double d1 = Double.parseDouble(result.getFractionalPart().toPlainString());
+ BigInteger subDigsO = BigInteger.valueOf((int) (dO * 32768 + 0.5));
+ BigInteger subDigsB = BigInteger.valueOf((int) (d1 * 32768 + 0.5));
+
+ if (subDigsO.equals(subDigsB)) {
+ return;
+ }
+ BigInteger diff = subDigsB.subtract(subDigsO).abs();
+ // 100/32768 ~= 0.003
+ assertTrue(diff.intValue() <= 100, "minor mistake");
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberComparer.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberComparer.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberComparer.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberComparer.java Sat May 22 20:56:44 2021
@@ -34,66 +34,66 @@ import org.junit.jupiter.params.provider
final class TestNumberComparer {
@Test
- void testAllComparisonExamples() {
- ComparisonExample[] examples = NumberComparisonExamples.getComparisonExamples();
- boolean success = true;
-
- for(int i=0;i<examples.length; i++) {
- ComparisonExample ce = examples[i];
- success &= confirm(i, ce.getA(), ce.getB(), +ce.getExpectedResult());
- success &= confirm(i, ce.getB(), ce.getA(), -ce.getExpectedResult());
- success &= confirm(i, ce.getNegA(), ce.getNegB(), -ce.getExpectedResult());
- success &= confirm(i, ce.getNegB(), ce.getNegA(), +ce.getExpectedResult());
- }
+ void testAllComparisonExamples() {
+ ComparisonExample[] examples = NumberComparisonExamples.getComparisonExamples();
+ boolean success = true;
+
+ for(int i=0;i<examples.length; i++) {
+ ComparisonExample ce = examples[i];
+ success &= confirm(i, ce.getA(), ce.getB(), +ce.getExpectedResult());
+ success &= confirm(i, ce.getB(), ce.getA(), -ce.getExpectedResult());
+ success &= confirm(i, ce.getNegA(), ce.getNegB(), -ce.getExpectedResult());
+ success &= confirm(i, ce.getNegB(), ce.getNegA(), +ce.getExpectedResult());
+ }
- assertTrue(success, "One or more cases failed. See stderr");
- }
+ assertTrue(success, "One or more cases failed. See stderr");
+ }
@ParameterizedTest
- @MethodSource("org.apache.poi.ss.util.NumberComparisonExamples#getComparisonExamples")
- void testRoundTripOnComparisonExamples(ComparisonExample ce) {
- double[] vals = { ce.getA(), ce.getNegA(), ce.getB(), ce.getNegB() };
- for (double a : vals) {
- assertDoesNotThrow(() -> new TestExpandedDouble().confirmRoundTrip(Double.doubleToLongBits(a)));
- }
- }
-
- /**
- * The actual example from bug 47598
- */
- @Test
- void testSpecificExampleA() {
- double a = 0.06-0.01;
- double b = 0.05;
+ @MethodSource("org.apache.poi.ss.util.NumberComparisonExamples#getComparisonExamples")
+ void testRoundTripOnComparisonExamples(ComparisonExample ce) {
+ double[] vals = { ce.getA(), ce.getNegA(), ce.getB(), ce.getNegB() };
+ for (double a : vals) {
+ assertDoesNotThrow(() -> new TestExpandedDouble().confirmRoundTrip(Double.doubleToLongBits(a)));
+ }
+ }
+
+ /**
+ * The actual example from bug 47598
+ */
+ @Test
+ void testSpecificExampleA() {
+ double a = 0.06-0.01;
+ double b = 0.05;
assertNotEquals(a, b, 0.0);
- assertEquals(0, NumberComparer.compare(a, b));
- }
+ assertEquals(0, NumberComparer.compare(a, b));
+ }
- /**
- * The example from the nabble posting
- */
- @Test
- void testSpecificExampleB() {
- double a = 1+1.0028-0.9973;
- double b = 1.0055;
+ /**
+ * The example from the nabble posting
+ */
+ @Test
+ void testSpecificExampleB() {
+ double a = 1+1.0028-0.9973;
+ double b = 1.0055;
assertNotEquals(a, b, 0.0);
- assertEquals(0, NumberComparer.compare(a, b));
- }
+ assertEquals(0, NumberComparer.compare(a, b));
+ }
- private static boolean confirm(int i, double a, double b, int expRes) {
- int actRes = NumberComparer.compare(a, b);
+ private static boolean confirm(int i, double a, double b, int expRes) {
+ int actRes = NumberComparer.compare(a, b);
- int sgnActRes = Integer.compare(actRes, 0);
- if (sgnActRes != expRes) {
- System.err.println("Mismatch example[" + i + "] ("
- + formatDoubleAsHex(a) + ", " + formatDoubleAsHex(b) + ") expected "
- + expRes + " but got " + sgnActRes);
- return false;
- }
- return true;
- }
- private static String formatDoubleAsHex(double d) {
- long l = Double.doubleToLongBits(d);
- return HexDump.longToHex(l)+'L';
- }
+ int sgnActRes = Integer.compare(actRes, 0);
+ if (sgnActRes != expRes) {
+ System.err.println("Mismatch example[" + i + "] ("
+ + formatDoubleAsHex(a) + ", " + formatDoubleAsHex(b) + ") expected "
+ + expRes + " but got " + sgnActRes);
+ return false;
+ }
+ return true;
+ }
+ private static String formatDoubleAsHex(double d) {
+ long l = Double.doubleToLongBits(d);
+ return HexDump.longToHex(l)+'L';
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberToTextConverter.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberToTextConverter.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberToTextConverter.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestNumberToTextConverter.java Sat May 22 20:56:44 2021
@@ -31,66 +31,66 @@ import org.junit.jupiter.api.Test;
* Tests for {@link NumberToTextConverter}
*/
final class TestNumberToTextConverter {
- /**
- * Confirms that {@code ExcelNumberToTextConverter.toText(d)} produces the right results.
- * As part of preparing this test class, the {@code ExampleConversion} instances should be set
- * up to contain the rendering as produced by Excel.
- */
- @Test
- void testAll() {
- ExampleConversion[] examples = NumberToTextConversionExamples.getExampleConversions();
+ /**
+ * Confirms that {@code ExcelNumberToTextConverter.toText(d)} produces the right results.
+ * As part of preparing this test class, the {@code ExampleConversion} instances should be set
+ * up to contain the rendering as produced by Excel.
+ */
+ @Test
+ void testAll() {
+ ExampleConversion[] examples = NumberToTextConversionExamples.getExampleConversions();
- for (ExampleConversion example : examples) {
- if (example.isNaN()) {
- confirmNaN(example.getRawDoubleBits(), example.getExcelRendering());
- continue;
- }
- String actual = NumberToTextConverter.toText(example.getDoubleValue());
- assertEquals(example.getExcelRendering(), actual);
- }
- }
+ for (ExampleConversion example : examples) {
+ if (example.isNaN()) {
+ confirmNaN(example.getRawDoubleBits(), example.getExcelRendering());
+ continue;
+ }
+ String actual = NumberToTextConverter.toText(example.getDoubleValue());
+ assertEquals(example.getExcelRendering(), actual);
+ }
+ }
- /**
- * Excel's abnormal rendering of NaNs is both difficult to test and even reproduce in java. In
- * general, Excel does not attempt to use raw NaN in the IEEE sense. In {@link FormulaRecord}s,
- * Excel uses the NaN bit pattern to flag non-numeric (text, boolean, error) cached results.
- * If the formula result actually evaluates to raw NaN, Excel transforms it to <i>#NUM!</i>.
- * In other places (e.g. {@link NumberRecord}, {@link NumberPtg}, array items (via {@link
- * ConstantValueParser}), there seems to be no special NaN translation scheme. If a NaN bit
- * pattern is somehow encoded into any of these places Excel actually attempts to render the
- * values as a plain number. That is the unusual functionality that this method is testing.<p>
- *
- * There are multiple encodings (bit patterns) for NaN, and CPUs and applications can convert
- * to a preferred NaN encoding (Java prefers {@code 0x7FF8000000000000L}). Besides the
- * special encoding in {@code FormulaRecord.SpecialCachedValue}, it is not known how/whether
- * Excel attempts to encode NaN values.
- *
- * Observed NaN behaviour on HotSpot/Windows:
- * {@code Double.longBitsToDouble()} will set one bit 51 (the NaN signaling flag) if it isn't
- * already. {@code Double.doubleToLongBits()} will return a double with bit pattern
- * {@code 0x7FF8000000000000L} for any NaN bit pattern supplied.<br>
- * Differences are likely to be observed with other architectures.<p>
- *
- * <p>
- * The few test case examples calling this method represent functionality which may not be
- * important for POI to support.
- */
- private void confirmNaN(long l, String excelRep) {
- double d = Double.longBitsToDouble(l);
- assertEquals("NaN", Double.toString(d));
+ /**
+ * Excel's abnormal rendering of NaNs is both difficult to test and even reproduce in java. In
+ * general, Excel does not attempt to use raw NaN in the IEEE sense. In {@link FormulaRecord}s,
+ * Excel uses the NaN bit pattern to flag non-numeric (text, boolean, error) cached results.
+ * If the formula result actually evaluates to raw NaN, Excel transforms it to <i>#NUM!</i>.
+ * In other places (e.g. {@link NumberRecord}, {@link NumberPtg}, array items (via {@link
+ * ConstantValueParser}), there seems to be no special NaN translation scheme. If a NaN bit
+ * pattern is somehow encoded into any of these places Excel actually attempts to render the
+ * values as a plain number. That is the unusual functionality that this method is testing.<p>
+ *
+ * There are multiple encodings (bit patterns) for NaN, and CPUs and applications can convert
+ * to a preferred NaN encoding (Java prefers {@code 0x7FF8000000000000L}). Besides the
+ * special encoding in {@code FormulaRecord.SpecialCachedValue}, it is not known how/whether
+ * Excel attempts to encode NaN values.
+ *
+ * Observed NaN behaviour on HotSpot/Windows:
+ * {@code Double.longBitsToDouble()} will set one bit 51 (the NaN signaling flag) if it isn't
+ * already. {@code Double.doubleToLongBits()} will return a double with bit pattern
+ * {@code 0x7FF8000000000000L} for any NaN bit pattern supplied.<br>
+ * Differences are likely to be observed with other architectures.<p>
+ *
+ * <p>
+ * The few test case examples calling this method represent functionality which may not be
+ * important for POI to support.
+ */
+ private void confirmNaN(long l, String excelRep) {
+ double d = Double.longBitsToDouble(l);
+ assertEquals("NaN", Double.toString(d));
- String strExcel = NumberToTextConverter.rawDoubleBitsToText(l);
+ String strExcel = NumberToTextConverter.rawDoubleBitsToText(l);
- assertEquals(excelRep, strExcel);
- }
+ assertEquals(excelRep, strExcel);
+ }
- @Test
- void testSimpleRendering_bug56156() {
- double dResult = 0.05+0.01; // values chosen to produce rounding anomaly
- String actualText = NumberToTextConverter.toText(dResult);
- String jdkText = Double.toString(dResult);
- // "0.060000000000000005"
- assertNotEquals("Should not use default JDK IEEE double rendering", jdkText, actualText);
- assertEquals("0.06", actualText);
- }
+ @Test
+ void testSimpleRendering_bug56156() {
+ double dResult = 0.05+0.01; // values chosen to produce rounding anomaly
+ String actualText = NumberToTextConverter.toText(dResult);
+ String jdkText = Double.toString(dResult);
+ // "0.060000000000000005"
+ assertNotEquals("Should not use default JDK IEEE double rendering", jdkText, actualText);
+ assertEquals("0.06", actualText);
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java Sat May 22 20:56:44 2021
@@ -208,8 +208,8 @@ final class TestSheetUtil {
Cell cell = row.createCell(0);
cell.setCellValue((String)null);
- //noinspection deprecation
- cell.setCellType(CellType.STRING);
+ //noinspection deprecation
+ cell.setCellType(CellType.STRING);
assertTrue(SheetUtil.getColumnWidth(sheet, 0, true) > 0, "Having some width for rows with actual cells");
assertEquals(-1.0, SheetUtil.getColumnWidth(sheet, 0, true, 1, 2), 0.01, "Not having any widht for rows with all empty cells");
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestWorkbookUtil.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestWorkbookUtil.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestWorkbookUtil.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/TestWorkbookUtil.java Sat May 22 20:56:44 2021
@@ -27,64 +27,64 @@ import org.junit.jupiter.api.Test;
* @see org.apache.poi.ss.util.WorkbookUtil
*/
final class TestWorkbookUtil {
- /**
- * borrowed test cases from
- * {@link org.apache.poi.hssf.record.TestBoundSheetRecord#testValidNames()}
- */
- @Test
- void testCreateSafeNames() {
+ /**
+ * borrowed test cases from
+ * {@link org.apache.poi.hssf.record.TestBoundSheetRecord#testValidNames()}
+ */
+ @Test
+ void testCreateSafeNames() {
- String p = "Sheet1";
- String actual = WorkbookUtil.createSafeSheetName(p);
- assertEquals(p, actual);
+ String p = "Sheet1";
+ String actual = WorkbookUtil.createSafeSheetName(p);
+ assertEquals(p, actual);
- p = "O'Brien's sales";
- actual = WorkbookUtil.createSafeSheetName(p);
- assertEquals(p, actual);
+ p = "O'Brien's sales";
+ actual = WorkbookUtil.createSafeSheetName(p);
+ assertEquals(p, actual);
- p = " data # ";
- actual = WorkbookUtil.createSafeSheetName(p);
- assertEquals(p, actual);
+ p = " data # ";
+ actual = WorkbookUtil.createSafeSheetName(p);
+ assertEquals(p, actual);
- p = "data $1.00";
- actual = WorkbookUtil.createSafeSheetName(p);
- assertEquals(p, actual);
+ p = "data $1.00";
+ actual = WorkbookUtil.createSafeSheetName(p);
+ assertEquals(p, actual);
- // now the replaced versions ...
- actual = WorkbookUtil.createSafeSheetName("data?");
- assertEquals("data ", actual);
+ // now the replaced versions ...
+ actual = WorkbookUtil.createSafeSheetName("data?");
+ assertEquals("data ", actual);
- actual = WorkbookUtil.createSafeSheetName("abc/def");
- assertEquals("abc def", actual);
+ actual = WorkbookUtil.createSafeSheetName("abc/def");
+ assertEquals("abc def", actual);
- actual = WorkbookUtil.createSafeSheetName("data[0]");
- assertEquals("data 0 ", actual);
+ actual = WorkbookUtil.createSafeSheetName("data[0]");
+ assertEquals("data 0 ", actual);
- actual = WorkbookUtil.createSafeSheetName("data*");
- assertEquals("data ", actual);
+ actual = WorkbookUtil.createSafeSheetName("data*");
+ assertEquals("data ", actual);
- actual = WorkbookUtil.createSafeSheetName("abc\\def");
- assertEquals("abc def", actual);
+ actual = WorkbookUtil.createSafeSheetName("abc\\def");
+ assertEquals("abc def", actual);
- actual = WorkbookUtil.createSafeSheetName("'data");
- assertEquals(" data", actual);
+ actual = WorkbookUtil.createSafeSheetName("'data");
+ assertEquals(" data", actual);
- actual = WorkbookUtil.createSafeSheetName("data'");
- assertEquals("data ", actual);
+ actual = WorkbookUtil.createSafeSheetName("data'");
+ assertEquals("data ", actual);
- actual = WorkbookUtil.createSafeSheetName("d'at'a");
- assertEquals("d'at'a", actual);
+ actual = WorkbookUtil.createSafeSheetName("d'at'a");
+ assertEquals("d'at'a", actual);
- actual = WorkbookUtil.createSafeSheetName(null);
- assertEquals("null", actual);
+ actual = WorkbookUtil.createSafeSheetName(null);
+ assertEquals("null", actual);
- actual = WorkbookUtil.createSafeSheetName("");
- assertEquals("empty", actual);
+ actual = WorkbookUtil.createSafeSheetName("");
+ assertEquals("empty", actual);
- actual = WorkbookUtil.createSafeSheetName("1234567890123456789012345678901TOOLONG");
- assertEquals("1234567890123456789012345678901", actual);
+ actual = WorkbookUtil.createSafeSheetName("1234567890123456789012345678901TOOLONG");
+ assertEquals("1234567890123456789012345678901", actual);
actual = WorkbookUtil.createSafeSheetName("sheet:a4");
assertEquals("sheet a4", actual);
- }
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/util/cellwalk/TestCellWalk.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/util/cellwalk/TestCellWalk.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/util/cellwalk/TestCellWalk.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/util/cellwalk/TestCellWalk.java Sat May 22 20:56:44 2021
@@ -42,12 +42,12 @@ class TestCellWalk {
CellRangeAddress range = CellRangeAddress.valueOf("A1:C3");
CellWalk cellWalk = new CellWalk(sheet, range);
- int[] cellsVisited = { 0 };
- long[] ordinalNumberSum = { 0 };
+ int[] cellsVisited = { 0 };
+ long[] ordinalNumberSum = { 0 };
cellWalk.traverse((cell,ctx) -> {
- cellsVisited[0]++;
- ordinalNumberSum[0] += ctx.getOrdinalNumber();
- });
+ cellsVisited[0]++;
+ ordinalNumberSum[0] += ctx.getOrdinalNumber();
+ });
assertEquals(4, cellsVisited[0]);
/* 1 + 2 + 5 + 9 */
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/MemoryLeakVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/MemoryLeakVerifier.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/MemoryLeakVerifier.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/MemoryLeakVerifier.java Sat May 22 20:56:44 2021
@@ -28,18 +28,18 @@ import java.util.List;
*
* Usage is something like
*
- * private final MemoryLeakVerifier verifier = new MemoryLeakVerifier();
+ * private final MemoryLeakVerifier verifier = new MemoryLeakVerifier();
- {@literal}After
- void tearDown() {
- verifier.assertGarbageCollected();
- }
-
- {@literal}Test
- void someTest() {
- ...
- verifier.addObject(object);
- }
+ {@literal}After
+ void tearDown() {
+ verifier.assertGarbageCollected();
+ }
+
+ {@literal}Test
+ void someTest() {
+ ...
+ verifier.addObject(object);
+ }
*
* This will verify at the end of the test if the object is actually removed by the
@@ -48,58 +48,58 @@ import java.util.List;
* Idea taken from http://stackoverflow.com/a/7410460/411846
*/
public class MemoryLeakVerifier {
- private static final int MAX_GC_ITERATIONS = 50;
- private static final int GC_SLEEP_TIME = 100;
+ private static final int MAX_GC_ITERATIONS = 50;
+ private static final int GC_SLEEP_TIME = 100;
- private final List<WeakReference<Object>> references = new ArrayList<>();
+ private final List<WeakReference<Object>> references = new ArrayList<>();
- public MemoryLeakVerifier() {
- }
+ public MemoryLeakVerifier() {
+ }
- public void addObject(Object object) {
- references.add(new WeakReference<>(object));
- }
-
- /**
- * Attempts to perform a full garbage collection so that all weak references will be removed. Usually only
- * a single GC is required, but there have been situations where some unused memory is not cleared up on the
- * first pass. This method performs a full garbage collection and then validates that the weak reference
- * now has been cleared. If it hasn't then the thread will sleep for 100 milliseconds and then retry up to
- * 50 more times. If after this the object still has not been collected then the assertion will fail.
- *
- * Based upon the method described in: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html
- */
- public void assertGarbageCollected() {
- assertGarbageCollected(MAX_GC_ITERATIONS);
- }
-
- /**
- * Used only for testing the class itself where we would like to fail faster than 5 seconds
- * @param maxIterations The number of times a GC will be invoked until a possible memory leak is reported
- */
- void assertGarbageCollected(int maxIterations) {
- try {
- for(WeakReference<Object> ref : references) {
- assertGarbageCollected(ref, maxIterations);
- }
- } catch (InterruptedException e) {
- // just ensure that we quickly return when the thread is interrupted
- }
- }
-
- private static void assertGarbageCollected(WeakReference<Object> ref, int maxIterations) throws InterruptedException {
- Runtime runtime = Runtime.getRuntime();
- for (int i = 0; i < maxIterations; i++) {
- runtime.runFinalization();
- runtime.gc();
- if (ref.get() == null)
- break;
-
- // Pause for a while and then go back around the loop to try again...
- //EventQueue.invokeAndWait(Procedure.NoOp); // Wait for the AWT event queue to have completed processing
- Thread.sleep(GC_SLEEP_TIME);
- }
+ public void addObject(Object object) {
+ references.add(new WeakReference<>(object));
+ }
+
+ /**
+ * Attempts to perform a full garbage collection so that all weak references will be removed. Usually only
+ * a single GC is required, but there have been situations where some unused memory is not cleared up on the
+ * first pass. This method performs a full garbage collection and then validates that the weak reference
+ * now has been cleared. If it hasn't then the thread will sleep for 100 milliseconds and then retry up to
+ * 50 more times. If after this the object still has not been collected then the assertion will fail.
+ *
+ * Based upon the method described in: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html
+ */
+ public void assertGarbageCollected() {
+ assertGarbageCollected(MAX_GC_ITERATIONS);
+ }
+
+ /**
+ * Used only for testing the class itself where we would like to fail faster than 5 seconds
+ * @param maxIterations The number of times a GC will be invoked until a possible memory leak is reported
+ */
+ void assertGarbageCollected(int maxIterations) {
+ try {
+ for(WeakReference<Object> ref : references) {
+ assertGarbageCollected(ref, maxIterations);
+ }
+ } catch (InterruptedException e) {
+ // just ensure that we quickly return when the thread is interrupted
+ }
+ }
+
+ private static void assertGarbageCollected(WeakReference<Object> ref, int maxIterations) throws InterruptedException {
+ Runtime runtime = Runtime.getRuntime();
+ for (int i = 0; i < maxIterations; i++) {
+ runtime.runFinalization();
+ runtime.gc();
+ if (ref.get() == null)
+ break;
+
+ // Pause for a while and then go back around the loop to try again...
+ //EventQueue.invokeAndWait(Procedure.NoOp); // Wait for the AWT event queue to have completed processing
+ Thread.sleep(GC_SLEEP_TIME);
+ }
- assertNull(ref.get(), "Object should not exist after " + MAX_GC_ITERATIONS + " collections, but still had: " + ref.get());
- }
+ assertNull(ref.get(), "Object should not exist after " + MAX_GC_ITERATIONS + " collections, but still had: " + ref.get());
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/TestArrayUtil.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/TestArrayUtil.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/TestArrayUtil.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/TestArrayUtil.java Sat May 22 20:56:44 2021
@@ -29,65 +29,65 @@ import org.junit.jupiter.api.Test;
* Unit test for ArrayUtil
*/
class TestArrayUtil {
- /**
- * Helper for testArrayMoveWithin
- */
- private Integer[] getIntsList() {
- return new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- }
-
- /**
- * Test to ensure that arrayMoveWithin works as expected
- */
- @Test
- void testArrayMoveWithin() {
- // moveFrom, moveTo, numToMove, values...
- Integer[][] data = {
- // Moving to a later point in the array
- // Shift 1 back
- { 4, 8, 1, 0, 1, 2, 3, 5, 6, 7, 8, 4, 9 },
- // Shift front 1 back
- { 0, 7, 1, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9 },
- // Shift 1 to end
- { 4, 9, 1, 0, 1, 2, 3, 5, 6, 7, 8, 9, 4 },
-
- // Moving to an earlier point in the array
- // Shift 1 forward
- { 8, 3, 1, 0, 1, 2, 8, 3, 4, 5, 6, 7, 9 },
- // Shift end 1 forward
- { 9, 2, 1, 0, 1, 9, 2, 3, 4, 5, 6, 7, 8 },
- // Shift 1 to front
- { 5, 0, 1, 5, 0, 1, 2, 3, 4, 6, 7, 8, 9 },
-
- // Moving many to a later point in the array
- // Shift 3 back
- { 2, 6, 3, 0, 1, 5, 6, 7, 8, 2, 3, 4, 9 },
- // Shift 3 to back
- { 2, 7, 3, 0, 1, 5, 6, 7, 8, 9, 2, 3, 4 },
- // Shift from 3 front
- { 0, 5, 3, 3, 4, 5, 6, 7, 0, 1, 2, 8, 9 },
-
- // Moving many to an earlier point in the array
- // Shift 3 forward
- { 6, 2, 3, 0, 1, 6, 7, 8, 2, 3, 4, 5, 9 },
- // Shift 3 to front
- { 6, 0, 3, 6, 7, 8, 0, 1, 2, 3, 4, 5, 9 },
- // Shift from 3 back
- { 7, 3, 3, 0, 1, 2, 7, 8, 9, 3, 4, 5, 6 }
- };
-
- for (Integer[] entry : data) {
- Integer[] ints = getIntsList();
- ArrayUtil.arrayMoveWithin(ints, entry[0], entry[1], entry[2]);
- assertArrayEquals(ints, Arrays.copyOfRange(entry, 3, 13));
- }
-
- // Check can't shift more than we have
- assertThrows(IllegalArgumentException.class, () -> ArrayUtil.arrayMoveWithin(getIntsList(), 7, 3, 5));
- // Good, we don't have 5 from 7 onwards
-
- // Check can't shift where would overshoot
- assertThrows(IllegalArgumentException.class, () -> ArrayUtil.arrayMoveWithin(getIntsList(), 2, 7, 5));
- // Good, we can't fit 5 in starting at 7
- }
+ /**
+ * Helper for testArrayMoveWithin
+ */
+ private Integer[] getIntsList() {
+ return new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ }
+
+ /**
+ * Test to ensure that arrayMoveWithin works as expected
+ */
+ @Test
+ void testArrayMoveWithin() {
+ // moveFrom, moveTo, numToMove, values...
+ Integer[][] data = {
+ // Moving to a later point in the array
+ // Shift 1 back
+ { 4, 8, 1, 0, 1, 2, 3, 5, 6, 7, 8, 4, 9 },
+ // Shift front 1 back
+ { 0, 7, 1, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9 },
+ // Shift 1 to end
+ { 4, 9, 1, 0, 1, 2, 3, 5, 6, 7, 8, 9, 4 },
+
+ // Moving to an earlier point in the array
+ // Shift 1 forward
+ { 8, 3, 1, 0, 1, 2, 8, 3, 4, 5, 6, 7, 9 },
+ // Shift end 1 forward
+ { 9, 2, 1, 0, 1, 9, 2, 3, 4, 5, 6, 7, 8 },
+ // Shift 1 to front
+ { 5, 0, 1, 5, 0, 1, 2, 3, 4, 6, 7, 8, 9 },
+
+ // Moving many to a later point in the array
+ // Shift 3 back
+ { 2, 6, 3, 0, 1, 5, 6, 7, 8, 2, 3, 4, 9 },
+ // Shift 3 to back
+ { 2, 7, 3, 0, 1, 5, 6, 7, 8, 9, 2, 3, 4 },
+ // Shift from 3 front
+ { 0, 5, 3, 3, 4, 5, 6, 7, 0, 1, 2, 8, 9 },
+
+ // Moving many to an earlier point in the array
+ // Shift 3 forward
+ { 6, 2, 3, 0, 1, 6, 7, 8, 2, 3, 4, 5, 9 },
+ // Shift 3 to front
+ { 6, 0, 3, 6, 7, 8, 0, 1, 2, 3, 4, 5, 9 },
+ // Shift from 3 back
+ { 7, 3, 3, 0, 1, 2, 7, 8, 9, 3, 4, 5, 6 }
+ };
+
+ for (Integer[] entry : data) {
+ Integer[] ints = getIntsList();
+ ArrayUtil.arrayMoveWithin(ints, entry[0], entry[1], entry[2]);
+ assertArrayEquals(ints, Arrays.copyOfRange(entry, 3, 13));
+ }
+
+ // Check can't shift more than we have
+ assertThrows(IllegalArgumentException.class, () -> ArrayUtil.arrayMoveWithin(getIntsList(), 7, 3, 5));
+ // Good, we don't have 5 from 7 onwards
+
+ // Check can't shift where would overshoot
+ assertThrows(IllegalArgumentException.class, () -> ArrayUtil.arrayMoveWithin(getIntsList(), 2, 7, 5));
+ // Good, we can't fit 5 in starting at 7
+ }
}
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/TestHexDump.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/TestHexDump.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/TestHexDump.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/TestHexDump.java Sat May 22 20:56:44 2021
@@ -159,7 +159,7 @@ class TestHexDump {
assertEquals("0x0000000000003FCD", HexDump.longToHex(16333));
}
- @Test
+ @Test
void testDumpToString() {
byte[] testArray = testArray();
String dump = HexDump.dump(testArray, 0, 0);
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/TestIOUtils.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/TestIOUtils.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/TestIOUtils.java Sat May 22 20:56:44 2021
@@ -45,7 +45,7 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
-@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE
+@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE
final class TestIOUtils {
private static File TMP;
private static final long LENGTH = 300 + new Random().nextInt(9000);
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndian.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndian.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndian.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndian.java Sat May 22 20:56:44 2021
@@ -88,8 +88,8 @@ final class TestLittleEndian {
{
56, 50, -113, -4, -63, -64, -13, 63, 76, -32, -42, -35, 60, -43, 3, 64
};
- /** 0x7ff8000000000000 encoded in little endian order */
- private static final byte[] _nan_double_array = HexRead.readFromString("00 00 00 00 00 00 F8 7F");
+ /** 0x7ff8000000000000 encoded in little endian order */
+ private static final byte[] _nan_double_array = HexRead.readFromString("00 00 00 00 00 00 F8 7F");
private static final double[] _doubles =
{
1.23456, 2.47912, Double.NaN
Modified: poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndianStreams.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndianStreams.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndianStreams.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/util/TestLittleEndianStreams.java Sat May 22 20:56:44 2021
@@ -33,85 +33,85 @@ import org.junit.jupiter.api.Test;
*/
final class TestLittleEndianStreams {
- @Test
- void testRead() throws IOException {
- UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream();
- try (LittleEndianOutputStream leo = new LittleEndianOutputStream(baos)) {
- leo.writeInt(12345678);
- leo.writeShort(12345);
- leo.writeByte(123);
- leo.writeShort(40000);
- leo.writeByte(200);
- leo.writeLong(1234567890123456789L);
- leo.writeDouble(123.456);
- }
-
- try (LittleEndianInputStream lei = new LittleEndianInputStream(baos.toInputStream())) {
- assertEquals(12345678, lei.readInt());
- assertEquals(12345, lei.readShort());
- assertEquals(123, lei.readByte());
- assertEquals(40000, lei.readUShort());
- assertEquals(200, lei.readUByte());
- assertEquals(1234567890123456789L, lei.readLong());
- assertEquals(123.456, lei.readDouble(), 0.0);
- }
- }
-
- /**
- * Up until svn r836101 {@link LittleEndianByteArrayInputStream#readFully(byte[], int, int)}
- * had an error which resulted in the data being read and written back to the source byte
- * array.
- */
- @Test
- void testReadFully() {
- byte[] srcBuf = HexRead.readFromString("99 88 77 66 55 44 33");
- LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf);
-
- // do initial read to increment the read index beyond zero
- assertEquals(0x8899, lei.readUShort());
-
- byte[] actBuf = new byte[4];
- lei.readFully(actBuf);
-
- assertFalse(actBuf[0] == 0x00 && srcBuf[0] == 0x77 && srcBuf[3] == 0x44,
- "Identified bug in readFully() - source buffer was modified");
-
- byte[] expBuf = HexRead.readFromString("77 66 55 44");
- assertArrayEquals(actBuf, expBuf);
- assertEquals(0x33, lei.readUByte());
- assertEquals(0, lei.available());
- }
-
- @Test
- void testBufferOverrun() {
- byte[] srcBuf = HexRead.readFromString("99 88 77");
- LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf);
-
- // do initial read to increment the read index beyond zero
- assertEquals(0x8899, lei.readUShort());
-
- // only one byte left, so this should fail
- RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
- assertTrue(ex.getMessage().contains("Buffer overrun"));
- }
-
- @Test
- void testBufferOverrunStartOffset() {
- byte[] srcBuf = HexRead.readFromString("99 88 77 88 99");
- LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf, 2);
-
- // only one byte left, so this should fail
- RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
- assertTrue(ex.getMessage().contains("Buffer overrun"));
- }
-
- @Test
- void testBufferOverrunStartOffset2() {
- byte[] srcBuf = HexRead.readFromString("99 88 77 88 99");
- LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf, 2, 2);
-
- // only one byte left, so this should fail
- RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
- assertTrue(ex.getMessage().contains("Buffer overrun"));
- }
+ @Test
+ void testRead() throws IOException {
+ UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream();
+ try (LittleEndianOutputStream leo = new LittleEndianOutputStream(baos)) {
+ leo.writeInt(12345678);
+ leo.writeShort(12345);
+ leo.writeByte(123);
+ leo.writeShort(40000);
+ leo.writeByte(200);
+ leo.writeLong(1234567890123456789L);
+ leo.writeDouble(123.456);
+ }
+
+ try (LittleEndianInputStream lei = new LittleEndianInputStream(baos.toInputStream())) {
+ assertEquals(12345678, lei.readInt());
+ assertEquals(12345, lei.readShort());
+ assertEquals(123, lei.readByte());
+ assertEquals(40000, lei.readUShort());
+ assertEquals(200, lei.readUByte());
+ assertEquals(1234567890123456789L, lei.readLong());
+ assertEquals(123.456, lei.readDouble(), 0.0);
+ }
+ }
+
+ /**
+ * Up until svn r836101 {@link LittleEndianByteArrayInputStream#readFully(byte[], int, int)}
+ * had an error which resulted in the data being read and written back to the source byte
+ * array.
+ */
+ @Test
+ void testReadFully() {
+ byte[] srcBuf = HexRead.readFromString("99 88 77 66 55 44 33");
+ LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf);
+
+ // do initial read to increment the read index beyond zero
+ assertEquals(0x8899, lei.readUShort());
+
+ byte[] actBuf = new byte[4];
+ lei.readFully(actBuf);
+
+ assertFalse(actBuf[0] == 0x00 && srcBuf[0] == 0x77 && srcBuf[3] == 0x44,
+ "Identified bug in readFully() - source buffer was modified");
+
+ byte[] expBuf = HexRead.readFromString("77 66 55 44");
+ assertArrayEquals(actBuf, expBuf);
+ assertEquals(0x33, lei.readUByte());
+ assertEquals(0, lei.available());
+ }
+
+ @Test
+ void testBufferOverrun() {
+ byte[] srcBuf = HexRead.readFromString("99 88 77");
+ LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf);
+
+ // do initial read to increment the read index beyond zero
+ assertEquals(0x8899, lei.readUShort());
+
+ // only one byte left, so this should fail
+ RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
+ assertTrue(ex.getMessage().contains("Buffer overrun"));
+ }
+
+ @Test
+ void testBufferOverrunStartOffset() {
+ byte[] srcBuf = HexRead.readFromString("99 88 77 88 99");
+ LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf, 2);
+
+ // only one byte left, so this should fail
+ RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
+ assertTrue(ex.getMessage().contains("Buffer overrun"));
+ }
+
+ @Test
+ void testBufferOverrunStartOffset2() {
+ byte[] srcBuf = HexRead.readFromString("99 88 77 88 99");
+ LittleEndianInput lei = new LittleEndianByteArrayInputStream(srcBuf, 2, 2);
+
+ // only one byte left, so this should fail
+ RuntimeException ex = assertThrows(RuntimeException.class, () -> lei.readFully(new byte[4]));
+ assertTrue(ex.getMessage().contains("Buffer overrun"));
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org