blob: 6a2b85bd5d62ab26c33da70c52ea2d6c4a63d3ee [file] [log] [blame]
package com.fasterxml.jackson.databind.jsontype.vld;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
/**
* Tests to verify working of customizable {@PolymorphicTypeValidator},
* see [databind#2195], regarding verification of base type checks.
*
* @since 2.10
*/
public class ValidatePolymBaseTypeTest extends BaseMapTest
{
// // // Value types
static abstract class BaseValue {
public int x = 3;
}
static class BadValue extends BaseValue { }
static class GoodValue extends BaseValue { }
// // // Wrapper types
static final class AnnotatedGoodWrapper {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public GoodValue value;
protected AnnotatedGoodWrapper() { value = new GoodValue(); }
}
static final class AnnotatedBadWrapper {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public BadValue value;
protected AnnotatedBadWrapper() { value = new BadValue(); }
}
static final class DefTypeGoodWrapper {
public GoodValue value;
protected DefTypeGoodWrapper() { value = new GoodValue(); }
}
static final class DefTypeBadWrapper {
public BadValue value;
protected DefTypeBadWrapper() { value = new BadValue(); }
}
// // // Validator implementations
static class BaseTypeValidator extends PolymorphicTypeValidator {
private static final long serialVersionUID = 1L;
@Override
public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
final Class<?> raw = baseType.getRawClass();
if (raw == BadValue.class) {
return Validity.DENIED;
}
if (raw == GoodValue.class) {
return Validity.ALLOWED;
}
// defaults to denied, then:
return Validity.INDETERMINATE;
}
@Override
public Validity validateSubClassName(MapperConfig<?> ctxt, JavaType baseType, String subClassName) {
return Validity.DENIED;
}
@Override
public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType, JavaType subType) {
return Validity.DENIED;
}
}
// // // Mappers with Default Typing
// // // Mappers without Default Typing (explicit annotation needed)
private final ObjectMapper MAPPER_ANNOTATED = jsonMapperBuilder()
.polymorphicTypeValidator(new BaseTypeValidator())
.build();
private final ObjectMapper MAPPER_DEF_TYPING = jsonMapperBuilder()
// Since GoodBalue, BadValue not abstraction need to use non-final
.enableDefaultTyping(new BaseTypeValidator(), DefaultTyping.NON_FINAL)
.build();
/*
/**********************************************************************
/* Test methods: annotated
/**********************************************************************
*/
public void testAnnotedGood() throws Exception {
final String json = MAPPER_ANNOTATED.writeValueAsString(new AnnotatedGoodWrapper());
// should work ok
assertNotNull(MAPPER_DEF_TYPING.readValue(json, AnnotatedGoodWrapper.class));
}
public void testAnnotedBad() throws Exception {
final String json = MAPPER_ANNOTATED.writeValueAsString(new AnnotatedBadWrapper());
// should fail
try {
MAPPER_ANNOTATED.readValue(json, AnnotatedBadWrapper.class);
fail("Should not pass");
} catch (InvalidDefinitionException e) {
verifyException(e, "Configured `PolymorphicTypeValidator`");
verifyException(e, "denied resolution of");
verifyException(e, "all subtypes of base type");
}
}
/*
/**********************************************************************
/* Test methods: default typing
/**********************************************************************
*/
public void testDefaultGood() throws Exception {
final String json = MAPPER_DEF_TYPING.writeValueAsString(new DefTypeGoodWrapper());
// should work ok
assertNotNull(MAPPER_DEF_TYPING.readValue(json, DefTypeGoodWrapper.class));
}
public void testDefaultBad() throws Exception {
final String json = MAPPER_DEF_TYPING.writeValueAsString(new DefTypeBadWrapper());
// should fail
try {
MAPPER_DEF_TYPING.readValue(json, DefTypeBadWrapper.class);
fail("Should not pass");
} catch (InvalidDefinitionException e) {
verifyException(e, "Configured `PolymorphicTypeValidator`");
verifyException(e, "denied resolution of");
verifyException(e, "all subtypes of base type");
}
}
}