|
31 | 31 | import static org.junit.jupiter.api.Assertions.assertNotSame; |
32 | 32 | import static org.junit.jupiter.api.Assertions.assertNull; |
33 | 33 | import static org.junit.jupiter.api.Assertions.assertThrows; |
| 34 | +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; |
34 | 35 | import static org.junit.jupiter.api.Assertions.assertTrue; |
35 | 36 | import static org.junit.jupiter.api.Assertions.fail; |
36 | 37 |
|
|
45 | 46 | import java.lang.reflect.Modifier; |
46 | 47 | import java.sql.ResultSet; |
47 | 48 | import java.sql.SQLException; |
| 49 | +import java.time.Duration; |
48 | 50 | import java.util.Arrays; |
49 | 51 | import java.util.Objects; |
| 52 | +import java.util.concurrent.CountDownLatch; |
| 53 | +import java.util.concurrent.TimeUnit; |
50 | 54 |
|
51 | 55 | import org.apache.commons.csv.CSVFormat.Builder; |
52 | 56 | import org.junit.jupiter.api.Test; |
@@ -921,6 +925,37 @@ void testPrintRecordEmpty() throws IOException { |
921 | 925 | assertEquals(format.getRecordSeparator(), out.toString()); |
922 | 926 | } |
923 | 927 |
|
| 928 | + @Test |
| 929 | + void testPrintRecordNotBlockedByInstanceMonitor() throws Exception { |
| 930 | + // A CSVFormat is documented as thread-safe. Internal write locking uses a private lock, so external code |
| 931 | + // holding the format instance monitor must not be able to block a print call. |
| 932 | + final CSVFormat format = CSVFormat.RFC4180; |
| 933 | + final CountDownLatch holdingMonitor = new CountDownLatch(1); |
| 934 | + final CountDownLatch releaseMonitor = new CountDownLatch(1); |
| 935 | + final Thread holder = new Thread(() -> { |
| 936 | + synchronized (format) { |
| 937 | + holdingMonitor.countDown(); |
| 938 | + try { |
| 939 | + releaseMonitor.await(); |
| 940 | + } catch (final InterruptedException e) { |
| 941 | + Thread.currentThread().interrupt(); |
| 942 | + } |
| 943 | + } |
| 944 | + }); |
| 945 | + holder.start(); |
| 946 | + try { |
| 947 | + assertTrue(holdingMonitor.await(5, TimeUnit.SECONDS)); |
| 948 | + assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { |
| 949 | + final Appendable out = new StringBuilder(); |
| 950 | + format.printRecord(out, "a", "b", "c"); |
| 951 | + assertEquals("a,b,c" + format.getRecordSeparator(), out.toString()); |
| 952 | + }); |
| 953 | + } finally { |
| 954 | + releaseMonitor.countDown(); |
| 955 | + holder.join(); |
| 956 | + } |
| 957 | + } |
| 958 | + |
924 | 959 | @Test |
925 | 960 | void testPrintWithEscapesEndWithCRLF() throws IOException { |
926 | 961 | final Reader in = new StringReader("x,y,x\r\na,?b,c\r\n"); |
|
0 commit comments