package com.fasterxml.jackson.databind.misc;
import java.util.*;
import java.util.concurrent.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class RaceCondition738Test extends BaseMapTest
{
static abstract class AbstractHasSubTypes implements HasSubTypes { }
static class TypeOne extends AbstractHasSubTypes {
private final String id;
public TypeOne(String id) {
this.id = id;
}
@JsonProperty
public String getId() {
return id;
}
@Override
public String getType() {
return TypeOne.class.getSimpleName();
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
@JsonSubTypes.Type(value = TypeOne.class, name = "one")
})
public interface HasSubTypes {
String getType();
}
static class Wrapper {
private final HasSubTypes hasSubTypes;
private Wrapper(HasSubTypes hasSubTypes) {
this.hasSubTypes = hasSubTypes;
}
@JsonProperty
public HasSubTypes getHasSubTypes() {
return hasSubTypes;
}
}
/*
/**********************************************************
/* Test methods
/**********************************************************
*/
public void testRepeatedly() throws Exception {
final int COUNT = 2000;
for (int i = 0; i < COUNT; i++) {
runOnce(i, COUNT);
}
}
void runOnce(int round, int max) throws Exception {
final ObjectMapper mapper = getObjectMapper();
Callable<String> writeJson = new Callable<String>() {
@Override
public String call() throws Exception {
Wrapper wrapper = new Wrapper(new TypeOne("test"));
return mapper.writeValueAsString(wrapper);
}
};
int numThreads = 4;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
List<Future<String>> jsonFutures = new ArrayList<Future<String>>();
for (int i = 0; i < numThreads; i++) {
jsonFutures.add(executor.submit(writeJson));
}
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
for (Future<String> jsonFuture : jsonFutures) {
String json = jsonFuture.get();
JsonNode tree = mapper.readTree(json);
JsonNode wrapped = tree.get("hasSubTypes");
if (!wrapped.has("one")) {
throw new IllegalStateException("Round #"+round+"/"+max+" ; missing property 'one', source: "+json);
}
}
}
private static ObjectMapper getObjectMapper() {
return new ObjectMapper();
}
}