]> source.dussan.org Git - poi.git/commitdiff
Bug 68778: Verify "ignoreMissingFontSystem" for SheetUtil.getDefaultCharWidthAsFloat()
authorDominik Stadler <centic@apache.org>
Thu, 14 Mar 2024 13:20:47 +0000 (13:20 +0000)
committerDominik Stadler <centic@apache.org>
Thu, 14 Mar 2024 13:20:47 +0000 (13:20 +0000)
This functionality saw some regressions at times and thus
should be verified via unit-tests.

We can simulate failures in the low-level font-system by
mocking the FontRenderContext and triggering exceptions
from there.

This hopefully now verifies behavior of
SheetUtil.getDefaultCharWidthAsFloat() both with
"ignoreMissingFontSystem" enabled and disabled.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1916297 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/ss/util/SheetUtil.java
poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java

index cc5abe81b1cf923eb5f1da26e84db5a9bbbf863e..f90d2298955289e83bce793234c839a291a1afe9 100644 (file)
@@ -96,13 +96,13 @@ public class SheetUtil {
     /**
      * drawing context to measure text
      */
-    private static final FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
+    private static FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
 
     /**
      * A system property which can be enabled to not fail when the
      * font-system is not available on the current machine
      */
-    private static final boolean ignoreMissingFontSystem =
+    private static boolean ignoreMissingFontSystem =
             Boolean.parseBoolean(System.getProperty("org.apache.poi.ss.ignoreMissingFontSystem"));
 
     /**
@@ -490,4 +490,21 @@ public class SheetUtil {
         //  live within any merged regions
         return null;
     }
+
+    // Getters/Setters are available to allow in-depth testing
+    protected static boolean isIgnoreMissingFontSystem() {
+        return ignoreMissingFontSystem;
+    }
+
+    protected static void setIgnoreMissingFontSystem(boolean value) {
+        ignoreMissingFontSystem = value;
+    }
+
+    protected static FontRenderContext getFontRenderContext() {
+        return fontRenderContext;
+    }
+
+    protected static void setFontRenderContext(FontRenderContext fontRenderContext) {
+        SheetUtil.fontRenderContext = fontRenderContext;
+    }
 }
index b63460596c85c45d5abd156ff9f6fcc42a0b8f11..4836b345fa93e611c70258cf91d14ec28ccbd376 100644 (file)
@@ -19,10 +19,14 @@ package org.apache.poi.ss.util;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
 
+import java.awt.font.FontRenderContext;
 import java.io.IOException;
 
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@@ -31,13 +35,16 @@ import org.apache.poi.ss.usermodel.CellType;
 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.ExceptionUtil;
 import org.junit.jupiter.api.Test;
+import org.mockito.stubbing.Answer;
 
 /**
  * Tests SheetUtil.
  *
  * @see org.apache.poi.ss.util.SheetUtil
  */
+@SuppressWarnings("deprecation")
 final class TestSheetUtil {
     @Test
     void testCellWithMerges() throws Exception {
@@ -220,4 +227,163 @@ final class TestSheetUtil {
             assertEquals(-1.0, SheetUtil.getColumnWidth(sheet, 0, true, 1, 2), 0.01, "Not having any width for rows with all empty cells");
         }
     }
+
+    @Test
+    void testIsFatal() {
+        assertFalse(ExceptionUtil.isFatal(new RuntimeException()),
+                "RuntimeException should not be regarded as 'fatal'");
+        assertTrue(ExceptionUtil.isFatal(new LinkageError()),
+                "LinkageError should not be regarded as 'fatal'");
+        assertTrue(ExceptionUtil.isFatal(new UnsatisfiedLinkError()),
+                "UnsatisfiedLinkError should not be regarded as 'fatal'");
+    }
+
+    @Test
+    void testGetCharWidthWithFonts() throws IOException {
+        // verify that normal call returns a useful value
+        // (may fail if font-system is missing, but then many other tests fail as well)
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            final float width = SheetUtil.getDefaultCharWidthAsFloat(wb);
+            assertTrue(width > 0,
+                    "Should get some useful char width, but had: " + width);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithInvalidFont() throws IOException {
+        // verify that a call with an unknown font-name returns a useful value
+        // (likely the font-system falls back to a default font here)
+        // (may fail if font-system is missing, but then many other tests fail as well)
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            wb.getFontAt(0).setFontName("invalid font");
+
+            final float width = SheetUtil.getDefaultCharWidthAsFloat(wb);
+            assertTrue(width > 0,
+                    "Should get some useful char width, but had: " + width);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithIgnoreEnabled() throws IOException {
+        boolean previous = SheetUtil.isIgnoreMissingFontSystem();
+        SheetUtil.setIgnoreMissingFontSystem(true);
+
+        // just verify that enabling the setting "ignoreMissingFontSystem"
+        // does not cause unexpected results
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            final float width = SheetUtil.getDefaultCharWidthAsFloat(wb);
+            assertTrue(width > 0,
+                    "Should get some useful char width, but had: " + width);
+        } finally {
+            // restore value
+            SheetUtil.setIgnoreMissingFontSystem(previous);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithMockedException() throws IOException {
+        FontRenderContext prevCtx = SheetUtil.getFontRenderContext();
+        final FontRenderContext ctx = mock(FontRenderContext.class, (Answer<Object>) invocation -> {
+            // simulate an exception in some of the calls to java.awt packages
+            throw new IllegalArgumentException("Test runtime exception");
+        });
+        SheetUtil.setFontRenderContext(ctx);
+
+        boolean previous = SheetUtil.isIgnoreMissingFontSystem();
+        SheetUtil.setIgnoreMissingFontSystem(false);
+
+        // verify that a RuntimeException in the font-system is
+        // thrown when "ignoreMissingFontSystem" is disabled
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            assertThrows(IllegalArgumentException.class,
+                    () -> SheetUtil.getDefaultCharWidthAsFloat(wb),
+                    "Should get an exception because ignoreMissingFontSystem = false");
+        } finally {
+            // restore values
+            SheetUtil.setFontRenderContext(prevCtx);
+            SheetUtil.setIgnoreMissingFontSystem(previous);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithMockedUnsatisfiedLinkError() throws IOException {
+        FontRenderContext prevCtx = SheetUtil.getFontRenderContext();
+        final FontRenderContext ctx = mock(FontRenderContext.class, (Answer<Object>) invocation -> {
+            // simulate an exception in some of the calls to java.awt packages
+            throw new UnsatisfiedLinkError("Test runtime exception");
+        });
+        SheetUtil.setFontRenderContext(ctx);
+
+        boolean previous = SheetUtil.isIgnoreMissingFontSystem();
+        SheetUtil.setIgnoreMissingFontSystem(false);
+
+        // verify that a UnsatisfiedLinkError in the font-system is
+        // thrown when "ignoreMissingFontSystem" is disabled
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            assertThrows(UnsatisfiedLinkError.class,
+                    () -> SheetUtil.getDefaultCharWidthAsFloat(wb),
+                    "Should get an exception because ignoreMissingFontSystem = false");
+        } finally {
+            // restore values
+            SheetUtil.setFontRenderContext(prevCtx);
+            SheetUtil.setIgnoreMissingFontSystem(previous);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithMockedExceptionAndIgnore() throws IOException {
+        FontRenderContext prevCtx = SheetUtil.getFontRenderContext();
+        final FontRenderContext ctx = mock(FontRenderContext.class, (Answer<Object>) invocation -> {
+            // simulate an exception in some of the calls to java.awt packages
+            throw new IllegalArgumentException("Test runtime exception");
+        });
+        SheetUtil.setFontRenderContext(ctx);
+
+        boolean previous = SheetUtil.isIgnoreMissingFontSystem();
+        SheetUtil.setIgnoreMissingFontSystem(true);
+
+        // verify that a RuntimeException in the font-system is
+        // ignored when "ignoreMissingFontSystem" is enabled
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            final float width = SheetUtil.getDefaultCharWidthAsFloat(wb);
+            assertEquals(SheetUtil.DEFAULT_CHAR_WIDTH, width,
+                    "Should get default char width because ignoreMissingFontSystem = true, but had: " + width);
+        } finally {
+            // restore values
+            SheetUtil.setFontRenderContext(prevCtx);
+            SheetUtil.setIgnoreMissingFontSystem(previous);
+        }
+    }
+
+    @Test
+    void testGetCharWidthWithMockedUnsatisfiedLinkErrorAndIgnore() throws IOException {
+        FontRenderContext prevCtx = SheetUtil.getFontRenderContext();
+        final FontRenderContext ctx = mock(FontRenderContext.class, (Answer<Object>) invocation -> {
+            // simulate an exception in some of the calls to java.awt packages
+            throw new UnsatisfiedLinkError("Test runtime exception");
+        });
+        SheetUtil.setFontRenderContext(ctx);
+
+        boolean previous = SheetUtil.isIgnoreMissingFontSystem();
+        SheetUtil.setIgnoreMissingFontSystem(true);
+
+        // verify that a UnsatisfiedLinkError in the font-system is
+        // ignored when "ignoreMissingFontSystem" is enabled
+
+        try (Workbook wb = new HSSFWorkbook()) {
+            final float width = SheetUtil.getDefaultCharWidthAsFloat(wb);
+            assertEquals(SheetUtil.DEFAULT_CHAR_WIDTH, width,
+                    "Should get default char width because ignoreMissingFontSystem = true, but had: " + width);
+        } finally {
+            // restore values
+            SheetUtil.setFontRenderContext(prevCtx);
+            SheetUtil.setIgnoreMissingFontSystem(previous);
+        }
+    }
 }