[prev in list] [next in list] [prev in thread] [next in thread] 

List:       poi-dev
Subject:    [Bug 63291] New: CellFormat global cache isn't thread-safe
From:       bugzilla () apache ! org
Date:       2019-03-27 17:55:14
Message-ID: bug-63291-47293 () https ! bz ! apache ! org/bugzilla/
[Download RAW message or body]

https://bz.apache.org/bugzilla/show_bug.cgi?id=63291

            Bug ID: 63291
           Summary: CellFormat global cache isn't thread-safe
           Product: POI
           Version: 4.0.0-FINAL
          Hardware: PC
                OS: Mac OS X 10.1
            Status: NEW
          Severity: normal
          Priority: P2
         Component: SS Common
          Assignee: dev@poi.apache.org
          Reporter: shawn@thena.net
  Target Milestone: ---

CellFormat.getInstance() uses a global static cache which shares CellFormat
instances across threads.  But a CellFormat with a CellDateFormatter wraps a
java.text.SimpleDateFormat which isn't thread-safe.  The result is that calls
like DataFormatter.formatCellValue() aren't thread-safe even when each thread
uses a different instance of DataFormatter.

Here's a test case that reproduces the problem.  If you remove the parallelism
from this test then it passes, otherwise it almost always fails:

import org.apache.poi.ss.usermodel.DataFormatter;
import org.junit.Test;

import java.util.concurrent.CompletableFuture;

import static org.junit.Assert.assertEquals;

public class FormatterTest {
    @Test
    public void testCellFormat() {
        int formatIndex = 105;
        String formatString = "[$-F400]m/d/yy h:mm:ss\\ AM/PM;[$-F400]m/d/yy
h:mm:ss\\ AM/PM;_-* \"\"??_-;_-@_-";

        CompletableFuture<Void> future1 = CompletableFuture.runAsync(
                () -> doFormatTest(43551.50990171296, "3/27/19 12:14:15 PM",
formatIndex, formatString));
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(
                () -> doFormatTest(36104.424780092595, "11/5/98 10:11:41 AM",
formatIndex, formatString));
        future1.join();
        future2.join();
    }

    private void doFormatTest(double n, String expected, int formatIndex,
String formatString) {
        DataFormatter formatter = new DataFormatter();
        for (int i = 0; i < 1_000; i++) {
            String actual = formatter.formatRawCellContents(n, formatIndex,
formatString);
            assertEquals("Failed on iteration " + i, expected, actual);
        }
    }
}

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic