Skip to content

Commit 6655a7a

Browse files
committed
Add test for #1759, passes for now (and fails with trivial forced race condition)
1 parent 0bb4750 commit 6655a7a

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/test/java/com/fasterxml/jackson/databind/misc/RaceCondition738Test.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void testRepeatedly() throws Exception {
6363
}
6464

6565
void runOnce(int round, int max) throws Exception {
66-
final ObjectMapper mapper = getObjectMapper();
66+
final ObjectMapper mapper = newObjectMapper();
6767
Callable<String> writeJson = new Callable<String>() {
6868
@Override
6969
public String call() throws Exception {
@@ -92,8 +92,4 @@ public String call() throws Exception {
9292
}
9393
}
9494
}
95-
96-
private static ObjectMapper getObjectMapper() {
97-
return new ObjectMapper();
98-
}
9995
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.fasterxml.jackson.databind.misc;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Date;
6+
import java.util.List;
7+
import java.util.concurrent.*;
8+
import java.util.concurrent.atomic.AtomicInteger;
9+
10+
import com.fasterxml.jackson.databind.*;
11+
12+
public class ThreadSafety1759Test extends BaseMapTest
13+
{
14+
/*
15+
/**********************************************************
16+
/* Test methods
17+
/**********************************************************
18+
*/
19+
20+
public void testCalendarForDeser() throws Exception
21+
{
22+
final ObjectMapper mapper = newObjectMapper();
23+
24+
final int numThreads = 4;
25+
final int COUNT = 3000;
26+
final AtomicInteger counter = new AtomicInteger();
27+
28+
// IMPORTANT! Use different timestamp for every thread
29+
List<Callable<Throwable>> calls = new ArrayList<Callable<Throwable>>();
30+
for (int thread = 1; thread <= numThreads; ++thread) {
31+
final String json = quote(String.format("2017-01-%02dT16:30:49Z", thread));
32+
final long timestamp = mapper.readValue(json, Date.class).getTime();
33+
34+
calls.add(createCallable(thread, mapper, json, timestamp, COUNT, counter));
35+
}
36+
37+
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
38+
List<Future<Throwable>> results = new ArrayList<>();
39+
for (Callable<Throwable> c : calls) {
40+
results.add(executor.submit(c));
41+
}
42+
executor.shutdown();
43+
for (Future<Throwable> f : results) {
44+
Throwable t = f.get(5, TimeUnit.SECONDS);
45+
if (t != null) {
46+
fail("Exception during processing: "+t.getMessage());
47+
}
48+
}
49+
assertEquals(numThreads * COUNT, counter.get());
50+
}
51+
52+
private Callable<Throwable> createCallable(final int threadId,
53+
final ObjectMapper mapper,
54+
final String json, final long timestamp,
55+
final int count, final AtomicInteger counter)
56+
{
57+
return new Callable<Throwable>() {
58+
@Override
59+
public Throwable call() throws IOException {
60+
for (int i = 0; i < count; ++i) {
61+
Date dt = mapper.readValue(json, Date.class);
62+
if (dt.getTime() != timestamp) {
63+
return new IllegalArgumentException("Wrong timestamp (thread id "+threadId+", input: "+json+": should get "+timestamp+", got "+dt.getTime());
64+
}
65+
counter.addAndGet(1);
66+
}
67+
return null;
68+
}
69+
};
70+
}
71+
}

0 commit comments

Comments
 (0)