Skip to content

Commit

Permalink
Add a test for #738
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Mar 27, 2015
1 parent 841a1a7 commit c568ff2
Showing 1 changed file with 136 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/test/java/com/fasterxml/jackson/failing/RaceCondition738Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.fasterxml.jackson.failing;

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;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class RaceCondition738Test extends BaseMapTest
{
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
@JsonSubTypes.Type(value = TypeOne.class, name = "one"),
@JsonSubTypes.Type(value = TypeTwo.class, name = "two"),
@JsonSubTypes.Type(value = TypeThree.class, name = "three")
})
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();
}
}

static class TypeTwo extends AbstractHasSubTypes {
private final String id;
public TypeTwo(String id) {
this.id = id;
}
@JsonProperty
public String getId() {
return id;
}
@Override
public String getType() {
return TypeTwo.class.getSimpleName();
}
}

static class TypeThree extends AbstractHasSubTypes {
private final String id;
public TypeThree(String id) {
this.id = id;
}
@JsonProperty
public String getId() {
return id;
}
@Override
public String getType() {
return TypeThree.class.getSimpleName();
}
}

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 {
for (int i = 0; i < 1000; i++) {
runOnce();
}
}

void runOnce() 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("Missing 'one', source: "+json);
}
}
}

private static ObjectMapper getObjectMapper() {
SimpleModule module = new SimpleModule("subTypeRace");
module.setMixInAnnotation(HasSubTypes.class, AbstractHasSubTypes.class);

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
return mapper;
}
}

0 comments on commit c568ff2

Please sign in to comment.