Author: lehmi
Date: Thu May 16 17:40:18 2024
New Revision: 1917766

URL: http://svn.apache.org/viewvc?rev=1917766&view=rev
Log:
PDFBOX-5819: added test to ensure the thread safety of Type2CharStringParser as 
provided by Patrick Corless

Modified:
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java

Modified: 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java?rev=1917766&r1=1917765&r2=1917766&view=diff
==============================================================================
--- 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java 
(original)
+++ 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java 
Thu May 16 17:40:18 2024
@@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Asse
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
@@ -117,8 +119,7 @@ class CFFParserTest
         assertFalse(charStringBytes.isEmpty());
         assertEquals(824, testCFFType1Font.getNumCharStrings());
         // check some randomly chosen values
-        assertTrue(
-                Arrays.equals(new byte[] { -4, 15, 14 }, 
charStringBytes.get(1)), //
+        assertTrue(Arrays.equals(new byte[] { -4, 15, 14 }, 
charStringBytes.get(1)), //
                 "Other char strings byte values than expected");
         assertTrue(
                 Arrays.equals(new byte[] { 72, 29, -13, 29, -9, -74, -9, 43, 
3, 33, 29, 14 },
@@ -159,10 +160,10 @@ class CFFParserTest
     }
 
     /**
-     * PDFBOX-4038: Test whether BlueValues and other delta encoded lists are 
read correctly. The
-     * test file is from FOP-2432.
+     * PDFBOX-4038: Test whether BlueValues and other delta encoded lists are 
read correctly. The test file is from
+     * FOP-2432.
      *
-     * @throws IOException 
+     * @throws IOException
      */
     @Test
     void testDeltaLists() throws IOException
@@ -171,34 +172,95 @@ class CFFParserTest
         List<Number> blues = (List<Number>) 
testCFFType1Font.getPrivateDict().get("BlueValues");
 
         // Expected values found for this font
-        assertNumberList("Blue values are different than expected: " + 
blues.toString(),                     
-                new int[]{-12, 0, 496, 508, 578, 590, 635, 647, 652, 664, 701, 
713}, blues);
+        assertNumberList("Blue values are different than expected: " + 
blues.toString(),
+                new int[] { -12, 0, 496, 508, 578, 590, 635, 647, 652, 664, 
701, 713 }, blues);
 
         @SuppressWarnings("unchecked")
-        List<Number> otherBlues = (List<Number>) 
testCFFType1Font.getPrivateDict().get("OtherBlues");
-        assertNumberList("Other blues are different than expected: " + 
otherBlues.toString(),                     
-                new int[]{-196, -184}, otherBlues);
+        List<Number> otherBlues = (List<Number>) 
testCFFType1Font.getPrivateDict()
+                .get("OtherBlues");
+        assertNumberList("Other blues are different than expected: " + 
otherBlues.toString(),
+                new int[] { -196, -184 }, otherBlues);
 
         @SuppressWarnings("unchecked")
-        List<Number> familyBlues = (List<Number>) 
testCFFType1Font.getPrivateDict().get("FamilyBlues");
-        assertNumberList("Other blues are different than expected: " + 
familyBlues.toString(),                     
-                new int[]{-12, 0, 486, 498, 574, 586, 638, 650, 656, 668, 712, 
724}, familyBlues);
+        List<Number> familyBlues = (List<Number>) 
testCFFType1Font.getPrivateDict()
+                .get("FamilyBlues");
+        assertNumberList("Other blues are different than expected: " + 
familyBlues.toString(),
+                new int[] { -12, 0, 486, 498, 574, 586, 638, 650, 656, 668, 
712, 724 },
+                familyBlues);
 
         @SuppressWarnings("unchecked")
         List<Number> familyOtherBlues = (List<Number>) 
testCFFType1Font.getPrivateDict()
                 .get("FamilyOtherBlues");
-        assertNumberList("Other blues are different than expected: " + 
familyOtherBlues.toString(),                     
-                new int[]{-217, -205}, familyOtherBlues);
+        assertNumberList("Other blues are different than expected: " + 
familyOtherBlues.toString(),
+                new int[] { -217, -205 }, familyOtherBlues);
 
         @SuppressWarnings("unchecked")
         List<Number> stemSnapH = (List<Number>) 
testCFFType1Font.getPrivateDict().get("StemSnapH");
-        assertNumberList("StemSnapH values are different than expected: " + 
stemSnapH.toString(),                     
-                new int[]{115}, stemSnapH);
+        assertNumberList("StemSnapH values are different than expected: " + 
stemSnapH.toString(),
+                new int[] { 115 }, stemSnapH);
 
         @SuppressWarnings("unchecked")
         List<Number> stemSnapV = (List<Number>) 
testCFFType1Font.getPrivateDict().get("StemSnapV");
-        assertNumberList("StemSnapV values are different than expected: " + 
stemSnapV.toString(),                     
-                new int[]{146, 150}, stemSnapV);
+        assertNumberList("StemSnapV values are different than expected: " + 
stemSnapV.toString(),
+                new int[] { 146, 150 }, stemSnapV);
+    }
+
+    /**
+     * PDFBOX-5819: ensure thread safety of Type2CharStringParser when parsing 
the path of a glyph.
+     * 
+     * @throws InterruptedException
+     */
+    @Test
+    void testMultiThreadParse() throws InterruptedException
+    {
+        CountDownLatch latch = new CountDownLatch(2);
+        PathRunner pathRunner1 = new PathRunner(latch);
+        PathRunner pathRunner2 = new PathRunner(latch);
+
+        AtomicBoolean wasCalled = new AtomicBoolean(false);
+
+        Thread.UncaughtExceptionHandler handler = (t, e) -> 
wasCalled.set(true);
+
+        Thread thread1 = new Thread(pathRunner1);
+        thread1.setUncaughtExceptionHandler(handler);
+        Thread thread2 = new Thread(pathRunner2);
+        thread2.setUncaughtExceptionHandler(handler);
+
+        thread1.start();
+        thread2.start();
+
+        latch.await();
+        assertFalse(wasCalled.get());
+    }
+
+    private class PathRunner implements Runnable
+    {
+        private final CountDownLatch latch;
+
+        public PathRunner(CountDownLatch latch)
+        {
+            this.latch = latch;
+        }
+
+        @Override
+        public void run()
+        {
+            try
+            {
+                for (int i = 33; i < 126; i++)
+                {
+                    testCFFType1Font.getPath(Character.toString(i));
+                }
+            }
+            catch (Exception e)
+            {
+                throw new IllegalStateException(e);
+            }
+            finally
+            {
+                latch.countDown();
+            }
+        }
     }
 
     private static List<CFFFont> readFont(String filename) throws IOException


Reply via email to