-
-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for CoercionConfig wrt int/boolean from "String" (since XML…
… has no native token types for those)
- Loading branch information
1 parent
3ad3995
commit e1e7cce
Showing
3 changed files
with
304 additions
and
4 deletions.
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
src/test/java/com/fasterxml/jackson/dataformat/xml/deser/convert/CoerceStringToIntsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package com.fasterxml.jackson.dataformat.xml.deser.convert; | ||
|
||
import java.math.BigInteger; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
|
||
import com.fasterxml.jackson.databind.*; | ||
import com.fasterxml.jackson.databind.cfg.CoercionAction; | ||
import com.fasterxml.jackson.databind.cfg.CoercionInputShape; | ||
import com.fasterxml.jackson.databind.type.LogicalType; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.XmlTestBase; | ||
|
||
// 2020-12-18, tatu: Modified from "jackson-databind" version: XML | ||
// backend MUST NOT prevent coercion from String since XML has no | ||
// native number representation (although TBH JsonParser.isExpectedNumberInt() | ||
// can work around that in many cases) | ||
public class CoerceStringToIntsTest | ||
extends XmlTestBase | ||
{ | ||
private final ObjectMapper DEFAULT_MAPPER = newMapper(); | ||
private final ObjectMapper MAPPER_LEGACY_FAIL = mapperBuilder() | ||
.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS) | ||
.build(); | ||
|
||
private final ObjectMapper MAPPER_TO_EMPTY; { | ||
MAPPER_TO_EMPTY = newMapper(); | ||
MAPPER_TO_EMPTY.coercionConfigFor(LogicalType.Integer) | ||
.setCoercion(CoercionInputShape.String, CoercionAction.AsEmpty); | ||
} | ||
|
||
private final ObjectMapper MAPPER_TRY_CONVERT; { | ||
MAPPER_TRY_CONVERT = newMapper(); | ||
MAPPER_TRY_CONVERT.coercionConfigFor(LogicalType.Integer) | ||
.setCoercion(CoercionInputShape.String, CoercionAction.TryConvert); | ||
} | ||
|
||
private final ObjectMapper MAPPER_TO_NULL; { | ||
MAPPER_TO_NULL = newMapper(); | ||
MAPPER_TO_NULL.coercionConfigFor(LogicalType.Integer) | ||
.setCoercion(CoercionInputShape.String, CoercionAction.AsNull); | ||
} | ||
|
||
private final ObjectMapper MAPPER_TO_FAIL; { | ||
MAPPER_TO_FAIL = newMapper(); | ||
MAPPER_TO_FAIL.coercionConfigFor(LogicalType.Integer) | ||
.setCoercion(CoercionInputShape.String, CoercionAction.Fail); | ||
} | ||
|
||
protected static class BooleanWrapper { | ||
public Boolean b; | ||
|
||
public BooleanWrapper() { } | ||
public BooleanWrapper(Boolean value) { b = value; } | ||
} | ||
|
||
protected static class IntWrapper { | ||
public int i; | ||
|
||
public IntWrapper() { } | ||
public IntWrapper(int value) { i = value; } | ||
} | ||
|
||
protected static class LongWrapper { | ||
public long l; | ||
|
||
public LongWrapper() { } | ||
public LongWrapper(long value) { l = value; } | ||
} | ||
|
||
protected static class DoubleWrapper { | ||
public double d; | ||
|
||
public DoubleWrapper() { } | ||
public DoubleWrapper(double value) { d = value; } | ||
} | ||
|
||
/* | ||
/******************************************************** | ||
/* Test methods, legacy setting | ||
/******************************************************** | ||
*/ | ||
|
||
// Works by default (as per databind defaulting); but also works | ||
// even if seemingly prevented -- this because XML has no native | ||
// number type and Strings present all scalar values, essentially | ||
|
||
public void testDefaultStringToIntCoercion() throws Exception { | ||
_verifyLegacyFromStringSucceeds(DEFAULT_MAPPER); | ||
} | ||
|
||
public void testLegacyFailStringToInt() throws Exception { | ||
_verifyLegacyFromStringSucceeds(MAPPER_LEGACY_FAIL); | ||
} | ||
|
||
private void _verifyLegacyFromStringSucceeds(ObjectMapper mapper) throws Exception | ||
{ | ||
// by default, should be ok | ||
Integer I = DEFAULT_MAPPER.readValue("<Integer>28</Integer>", Integer.class); | ||
assertEquals(28, I.intValue()); | ||
{ | ||
IntWrapper w = DEFAULT_MAPPER.readValue("<IntWrapper><i>37</i></IntWrapper>", | ||
IntWrapper.class); | ||
assertEquals(37, w.i); | ||
} | ||
|
||
Long L = DEFAULT_MAPPER.readValue("<Long>39</Long>", Long.class); | ||
assertEquals(39L, L.longValue()); | ||
{ | ||
LongWrapper w = DEFAULT_MAPPER.readValue("<LongWrapper><l>-13</l></LongWrapper>", | ||
LongWrapper.class); | ||
assertEquals(-13L, w.l); | ||
} | ||
|
||
Short S = DEFAULT_MAPPER.readValue("<Short>42</Short>", Short.class); | ||
assertEquals(42, S.intValue()); | ||
|
||
BigInteger biggie = DEFAULT_MAPPER.readValue("<BigInteger>95007</BigInteger>", BigInteger.class); | ||
assertEquals(95007, biggie.intValue()); | ||
|
||
AtomicLong atom = DEFAULT_MAPPER.readValue("<AtomicLong>25236</AtomicLong>", AtomicLong.class); | ||
assertEquals(25236L, atom.get()); | ||
} | ||
|
||
/* | ||
/******************************************************** | ||
/* Test methods, CoerceConfig, integers-from-String | ||
/******************************************************** | ||
*/ | ||
|
||
// When explicitly enabled, should pass | ||
|
||
public void testCoerceConfigStringToNull() throws Exception { | ||
_verifyCoercionFromStringSucceeds(MAPPER_TO_NULL); | ||
} | ||
|
||
// But even if blocked, or changed to null, should pass since with | ||
// XML, "String" is a native representation of numbers | ||
|
||
public void testCoerceConfigStringToEmpty() throws Exception { | ||
_verifyCoercionFromStringSucceeds(MAPPER_TO_EMPTY); | ||
} | ||
|
||
public void testCoerceConfigStringConvert() throws Exception { | ||
_verifyCoercionFromStringSucceeds(MAPPER_TRY_CONVERT); | ||
} | ||
|
||
public void testCoerceConfigFailFromString() throws Exception { | ||
_verifyCoercionFromStringSucceeds(MAPPER_TO_FAIL); | ||
} | ||
|
||
private void _verifyCoercionFromStringSucceeds(ObjectMapper mapper) throws Exception | ||
{ | ||
assertEquals(Integer.valueOf(12), mapper.readValue("<Integer>12</Integer>", Integer.class)); | ||
assertEquals(Integer.valueOf(34), mapper.readValue("<int>34</int>", Integer.TYPE)); | ||
{ | ||
IntWrapper w = mapper.readValue( "<IntWrapper i='-225' />", IntWrapper.class); | ||
assertEquals(-225, w.i); | ||
} | ||
|
||
assertEquals(Long.valueOf(34), mapper.readValue("<Long>34</Long>", Long.class)); | ||
assertEquals(Long.valueOf(534), mapper.readValue("<long>534</long>", Long.TYPE)); | ||
{ | ||
LongWrapper w = mapper.readValue("<LongWrapper><l>-225</l></LongWrapper>", | ||
LongWrapper.class); | ||
assertEquals(-225L, w.l); | ||
} | ||
|
||
assertEquals(Short.valueOf((short)12), mapper.readValue("<Short>12</Short>", Short.class)); | ||
assertEquals(Short.valueOf((short) 344), mapper.readValue("<short>344</short>", Short.TYPE)); | ||
|
||
assertEquals(Byte.valueOf((byte)12), mapper.readValue("<Byte>12</Byte>", Byte.class)); | ||
assertEquals(Byte.valueOf((byte) -99), mapper.readValue("<byte>-99</byte>", Byte.TYPE)); | ||
|
||
assertEquals(BigInteger.valueOf(1242L), | ||
mapper.readValue("<BigInteger>1242</BigInteger>", BigInteger.class)); | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
src/test/java/com/fasterxml/jackson/dataformat/xml/deser/convert/CoerceToBooleanTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.fasterxml.jackson.dataformat.xml.deser.convert; | ||
|
||
import java.io.IOException; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import com.fasterxml.jackson.databind.*; | ||
import com.fasterxml.jackson.databind.cfg.CoercionAction; | ||
import com.fasterxml.jackson.databind.cfg.CoercionInputShape; | ||
import com.fasterxml.jackson.databind.type.LogicalType; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.XmlTestBase; | ||
|
||
// 2020-12-18, tatu: Modified from "jackson-databind" version: XML | ||
// backend MUST NOT prevent coercion from String since XML has no | ||
// native boolean representation | ||
public class CoerceToBooleanTest | ||
extends XmlTestBase | ||
{ | ||
static class BooleanPOJO { | ||
public boolean value; | ||
|
||
public void setValue(boolean v) { value = v; } | ||
} | ||
|
||
private final ObjectMapper DEFAULT_MAPPER = newMapper(); | ||
|
||
private final ObjectMapper MAPPER_STRING_TO_BOOLEAN_FAIL; { | ||
MAPPER_STRING_TO_BOOLEAN_FAIL = newMapper(); | ||
MAPPER_STRING_TO_BOOLEAN_FAIL.coercionConfigFor(LogicalType.Boolean) | ||
.setCoercion(CoercionInputShape.String, CoercionAction.Fail); | ||
} | ||
|
||
private final ObjectMapper MAPPER_EMPTY_TO_BOOLEAN_FAIL; { | ||
MAPPER_EMPTY_TO_BOOLEAN_FAIL = newMapper(); | ||
MAPPER_EMPTY_TO_BOOLEAN_FAIL.coercionConfigFor(LogicalType.Boolean) | ||
.setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail); | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Test methods: default, legacy configuration, from String | ||
/********************************************************** | ||
*/ | ||
|
||
// for [databind#403] | ||
public void testEmptyStringFailForBooleanPrimitive() throws IOException | ||
{ | ||
final ObjectReader reader = MAPPER_EMPTY_TO_BOOLEAN_FAIL | ||
.readerFor(BooleanPOJO.class); | ||
try { | ||
reader.readValue("<BooleanPOJO><value></value></BooleanPOJO>"); | ||
fail("Expected failure for boolean + empty String"); | ||
} catch (JsonMappingException e) { | ||
verifyException(e, "Cannot coerce empty String"); | ||
verifyException(e, "to `boolean` value"); | ||
} | ||
} | ||
|
||
public void testDefaultStringToBooleanCoercionOk() throws Exception { | ||
_verifyStringToBooleanOk(DEFAULT_MAPPER); | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Test methods: CoercionConfig, from String | ||
/********************************************************** | ||
*/ | ||
|
||
public void testStringToBooleanOkDespiteCoercionConfig() throws Exception { | ||
_verifyStringToBooleanOk(MAPPER_STRING_TO_BOOLEAN_FAIL); | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Verification | ||
/********************************************************** | ||
*/ | ||
|
||
public void _verifyStringToBooleanOk(ObjectMapper mapper) throws Exception | ||
{ | ||
// first successful coercions, basic types: | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "true"), Boolean.TYPE, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "false"), Boolean.TYPE, Boolean.FALSE); | ||
|
||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "true"), Boolean.class, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "false"), Boolean.class, Boolean.FALSE); | ||
|
||
// and then allowed variants: | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "True"), Boolean.TYPE, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "True"), Boolean.class, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "TRUE"), Boolean.TYPE, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "TRUE"), Boolean.class, Boolean.TRUE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "False"), Boolean.TYPE, Boolean.FALSE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "False"), Boolean.class, Boolean.FALSE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("boolean", "FALSE"), Boolean.TYPE, Boolean.FALSE); | ||
_verifyCoerceSuccess(mapper, _xmlWrapped("Boolean", "FALSE"), Boolean.class, Boolean.FALSE); | ||
|
||
// and then Special boolean derivatives: | ||
// Alas, AtomicBoolean.equals() does not work so... | ||
final ObjectReader r = mapper.readerFor(AtomicBoolean.class); | ||
|
||
AtomicBoolean ab = r.readValue(_xmlWrapped("AtomicBoolean", "true")); | ||
assertTrue(ab.get()); | ||
|
||
ab = r.readValue(_xmlWrapped("AtomicBoolean", "false")); | ||
assertFalse(ab.get()); | ||
} | ||
|
||
/* | ||
/********************************************************** | ||
/* Other helper methods | ||
/********************************************************** | ||
*/ | ||
|
||
private String _xmlWrapped(String element, String value) { | ||
return String.format("<%s>%s</%s>", element, value, element); | ||
} | ||
|
||
private void _verifyCoerceSuccess(ObjectMapper mapper, | ||
String input, Class<?> type, Object exp) throws IOException | ||
{ | ||
Object result = mapper.readerFor(type) | ||
.readValue(input); | ||
assertEquals(exp.getClass(), result.getClass()); | ||
assertEquals(exp, result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters