JsonNodeShortValueTest.java
package tools.jackson.databind.node;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.exc.JsonNodeException;
import tools.jackson.databind.testutil.DatabindTestUtil;
import tools.jackson.databind.util.RawValue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for [databind#4958], JsonNode.intValue() (and related) parts
* over all types.
*<p>
* Also contains tests for {@code JsonNode.shortValue()}.
*/
public class JsonNodeShortValueTest
extends DatabindTestUtil
{
private final JsonNodeFactory NODES = newJsonMapper().getNodeFactory();
// // // shortValue()
@Test
public void shortValueFromNumberIntOk()
{
final short SHORT_1 = (short) 1;
final short MIN_SHORT = Short.MIN_VALUE;
final short MAX_SHORT = Short.MAX_VALUE;
// First safe from `short`
_assertShortValue(SHORT_1, NODES.numberNode((short) 1));
_assertShortValue(Short.MIN_VALUE, NODES.numberNode(MIN_SHORT));
_assertShortValue(Short.MAX_VALUE, NODES.numberNode(MAX_SHORT));
// Then other integer types
_assertShortValue(SHORT_1, NODES.numberNode((byte) 1));
_assertShortValue(Byte.MIN_VALUE, NODES.numberNode(Byte.MIN_VALUE));
_assertShortValue(Byte.MAX_VALUE, NODES.numberNode(Byte.MAX_VALUE));
_assertShortValue(SHORT_1, NODES.numberNode(1));
_assertShortValue(MIN_SHORT, NODES.numberNode((int) MIN_SHORT));
_assertShortValue(MAX_SHORT, NODES.numberNode((int) MAX_SHORT));
_assertShortValue(SHORT_1, NODES.numberNode(1L));
_assertShortValue(MIN_SHORT, NODES.numberNode((long) MIN_SHORT));
_assertShortValue(MAX_SHORT, NODES.numberNode((long) MAX_SHORT));
_assertShortValue(SHORT_1, NODES.numberNode(BigInteger.valueOf(1)));
_assertShortValue(MIN_SHORT, NODES.numberNode(BigInteger.valueOf(MIN_SHORT)));
_assertShortValue(MAX_SHORT, NODES.numberNode(BigInteger.valueOf(MAX_SHORT)));
}
@Test
public void shortValueFromNumberIntFailRange() {
// Can only fail for underflow/overflow: and that only for Long / BigInteger
final int underflow = -1 + Short.MIN_VALUE;
final int overflow = +1 + Short.MAX_VALUE;
_assertFailShortForValueRange(NODES.numberNode(underflow));
_assertFailShortForValueRange(NODES.numberNode(overflow));
_assertFailShortForValueRange(NODES.numberNode(BigInteger.valueOf(underflow)));
_assertFailShortForValueRange(NODES.numberNode(BigInteger.valueOf(overflow)));
}
@Test
public void shortValueFromNumberFPOk()
{
_assertShortValue((short) 1, NODES.numberNode(1.0f));
_assertShortValue((short) 10_000, NODES.numberNode(10_000.0f));
_assertShortValue((short) -10_000, NODES.numberNode(-10_000.0f));
_assertShortValue((short) 1, NODES.numberNode(1.0d));
_assertShortValue((short) 10_000, NODES.numberNode(10_000.0d));
_assertShortValue((short) -10_000, NODES.numberNode(-10_000.0d));
_assertShortValue(Short.MIN_VALUE, NODES.numberNode((double) Short.MIN_VALUE));
_assertShortValue(Short.MAX_VALUE, NODES.numberNode((double) Short.MAX_VALUE));
_assertShortValue((short) 1,
NODES.numberNode(BigDecimal.valueOf(1.0d)));
_assertShortValue(Short.MIN_VALUE,
NODES.numberNode(BigDecimal.valueOf((double) Short.MIN_VALUE)));
_assertShortValue(Short.MAX_VALUE,
NODES.numberNode(BigDecimal.valueOf((double) Short.MAX_VALUE)));
}
@Test
public void shortValueFromNumberFPFailRange()
{
// Can only fail for underflow/overflow: and that only for Long / BigInteger
final long underflow = Short.MIN_VALUE - 1L;
final long overflow = Short.MAX_VALUE + 1L;
_assertFailShortForValueRange(NODES.numberNode((double)underflow));
_assertFailShortForValueRange(NODES.numberNode((double)overflow));
// Float is too inexact for using same test as Double, so:
_assertFailShortForValueRange(NODES.numberNode(-Float.MAX_VALUE));
_assertFailShortForValueRange(NODES.numberNode(Float.MAX_VALUE));
_assertFailShortForValueRange(NODES.numberNode(BigDecimal.valueOf(underflow)));
_assertFailShortForValueRange(NODES.numberNode(BigDecimal.valueOf(overflow)));
}
@Test
public void shortValueFromNumberFPFailFraction()
{
_assertFailShortValueForFraction(NODES.numberNode(100.5f));
_assertFailShortValueForFraction(NODES.numberNode(-0.25f));
_assertFailShortValueForFraction(NODES.numberNode(100.5d));
_assertFailShortValueForFraction(NODES.numberNode(-0.25d));
_assertFailShortValueForFraction(NODES.numberNode(BigDecimal.valueOf(100.5d)));
_assertFailShortValueForFraction(NODES.numberNode(BigDecimal.valueOf(-0.25d)));
}
@Test
public void shortValueFromNonNumberFail()
{
_assertFailShortForNonNumber(NODES.booleanNode(true));
_assertFailShortForNonNumber(NODES.binaryNode(new byte[3]));
_assertFailShortForNonNumber(NODES.stringNode("123"));
_assertFailShortForNonNumber(NODES.rawValueNode(new RawValue("abc")));
_assertFailShortForNonNumber(NODES.pojoNode(Boolean.TRUE));
_assertFailShortForNonNumber(NODES.arrayNode(3));
_assertFailShortForNonNumber(NODES.objectNode());
_assertFailShortForNonNumber(NODES.nullNode());
_assertFailShortForNonNumber(NODES.missingNode());
_assertFailShortForNonNumber(NODES.pojoNode((short) 456));
}
// // // asShort()
// Numbers/Integers
@Test
public void asShortFromNumberIntOk()
{
// First safe from `short`
_assertAsShort((short) 1, NODES.numberNode((short) 1));
_assertAsShort(Short.MIN_VALUE, NODES.numberNode(Short.MIN_VALUE));
_assertAsShort(Short.MAX_VALUE, NODES.numberNode(Short.MAX_VALUE));
// Then other integer types
_assertAsShort((short) 1, NODES.numberNode((byte) 1));
_assertAsShort(Byte.MIN_VALUE, NODES.numberNode(Byte.MIN_VALUE));
_assertAsShort(Byte.MAX_VALUE, NODES.numberNode(Byte.MAX_VALUE));
_assertAsShort((short) 1, NODES.numberNode(1));
_assertAsShort(Short.MIN_VALUE, NODES.numberNode((int) Short.MIN_VALUE));
_assertAsShort(Short.MAX_VALUE, NODES.numberNode((int) Short.MAX_VALUE));
_assertAsShort((short) 1, NODES.numberNode(1L));
_assertAsShort(Short.MIN_VALUE, NODES.numberNode((long) Short.MIN_VALUE));
_assertAsShort(Short.MAX_VALUE, NODES.numberNode((long) Short.MAX_VALUE));
_assertAsShort((short) 1, NODES.numberNode(BigInteger.valueOf(1)));
_assertAsShort(Short.MIN_VALUE, NODES.numberNode(BigInteger.valueOf(Short.MIN_VALUE)));
_assertAsShort(Short.MAX_VALUE, NODES.numberNode(BigInteger.valueOf(Short.MAX_VALUE)));
}
@Test
public void asShortFromNumberIntFailRange() {
// Can only fail for underflow/overflow: and that only for Integer / Long / BigInteger
final int underflow = -1 + Short.MIN_VALUE;
final long overflow = +1L + Short.MAX_VALUE;
_assertAsShortFailForValueRange(NODES.numberNode(underflow));
_assertAsShortFailForValueRange(NODES.numberNode(overflow));
_assertAsShortFailForValueRange(NODES.numberNode(BigInteger.valueOf(underflow)));
_assertAsShortFailForValueRange(NODES.numberNode(BigInteger.valueOf(overflow)));
}
// Numbers/FPs
@Test
public void asShortFromNumberFPOk()
{
_assertAsShort((short) 1, NODES.numberNode(1.0f));
_assertAsShort((short) 100, NODES.numberNode(100.0f));
_assertAsShort((short) -100, NODES.numberNode(-100.0f));
_assertAsShort((short) 1, NODES.numberNode(1.0d));
_assertAsShort((short) 100, NODES.numberNode(100.0d));
_assertAsShort((short) -100, NODES.numberNode(-100.0d));
_assertAsShort(Short.MIN_VALUE, NODES.numberNode((double) Short.MIN_VALUE));
_assertAsShort(Short.MAX_VALUE, NODES.numberNode((double) Short.MAX_VALUE));
_assertAsShort((short) 1,
NODES.numberNode(BigDecimal.valueOf(1.0d)));
_assertAsShort(Short.MIN_VALUE,
NODES.numberNode(BigDecimal.valueOf((double) Short.MIN_VALUE)));
_assertAsShort(Short.MAX_VALUE,
NODES.numberNode(BigDecimal.valueOf((double) Short.MAX_VALUE)));
}
@Test
public void asShortFromNumberFPFailRange()
{
// Can only fail for underflow/overflow: and that only for Long / BigInteger
final long underflow = Short.MIN_VALUE - 1L;
final long overflow = Short.MAX_VALUE + 1L;
_assertAsShortFailForValueRange(NODES.numberNode((float)underflow));
_assertAsShortFailForValueRange(NODES.numberNode((double)overflow));
// Float is too inexact for using same test as Double, so:
_assertAsShortFailForValueRange(NODES.numberNode(-Float.MAX_VALUE));
_assertAsShortFailForValueRange(NODES.numberNode(Float.MAX_VALUE));
_assertAsShortFailForValueRange(NODES.numberNode(BigDecimal.valueOf(underflow)));
_assertAsShortFailForValueRange(NODES.numberNode(BigDecimal.valueOf(overflow)));
}
@Test
public void asShortFromNumberFPWithFraction()
{
_assertAsShort((short) 100, NODES.numberNode(100.75f));
_assertAsShort((short) -1, NODES.numberNode(-1.25f));
_assertAsShort((short) 100, NODES.numberNode(100.75d));
_assertAsShort((short) -1, NODES.numberNode(-1.25d));
_assertAsShort((short) 100, NODES.numberNode(BigDecimal.valueOf(100.75d)));
_assertAsShort((short) -1, NODES.numberNode(BigDecimal.valueOf(-1.25d)));
}
@Test
public void asIntFromNumberFPFailNaN()
{
_assertAsShortFailForNaN(NODES.numberNode(Float.NaN));
_assertAsShortFailForNaN(NODES.numberNode(Float.NEGATIVE_INFINITY));
_assertAsShortFailForNaN(NODES.numberNode(Float.POSITIVE_INFINITY));
_assertAsShortFailForNaN(NODES.numberNode(Double.NaN));
_assertAsShortFailForNaN(NODES.numberNode(Double.NEGATIVE_INFINITY));
_assertAsShortFailForNaN(NODES.numberNode(Double.POSITIVE_INFINITY));
}
// non-Numeric types
@Test
public void asShortFromNonNumberScalar()
{
// Some fail:
_assertAsShortFailForNonNumber(NODES.booleanNode(true));
_assertAsShortFailForNonNumber(NODES.binaryNode(new byte[3]));
_assertAsShortFailForNonNumber(NODES.rawValueNode(new RawValue("abc")));
_assertAsShortFailForNonNumber(NODES.pojoNode(Boolean.TRUE));
_assertAsShortFailForNonNumber(NODES.stringNode("abc"),
"value not a valid String representation of `short`");
_assertAsShortFailForNonNumber(NODES.pojoNode("123456"));
// Some pass:
_assertAsShort((short) 123, NODES.stringNode("123"));
_assertAsShort((short) 456, NODES.pojoNode(456));
_assertAsShort((short) 789, NODES.pojoNode(BigInteger.valueOf(789)));
}
@Test
public void asIntFromStructuralFail()
{
_assertAsShortFailForNonNumber(NODES.arrayNode(3));
_assertAsShortFailForNonNumber(NODES.objectNode());
}
@Test
public void asIntFromMiscOther()
{
// NullNode -> 0 but "missing" still fails
_assertAsShort((short) 0, NODES.nullNode());
_assertAsShortFailForNonNumber(NODES.missingNode());
}
// // // Shared helper methods: shortValue()
private void _assertShortValue(short expected, JsonNode node) {
assertEquals(expected, node.shortValue());
// and defaulting
assertEquals(expected, node.shortValue((short) 99));
assertEquals(expected, node.shortValueOpt().get());
}
// // // Shared helper methods
private void _assertFailShortForValueRange(JsonNode node) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.shortValue(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("cannot convert value")
.contains("value not in 16-bit `short` range");
// assert defaulting
assertEquals(99, node.shortValue((short) 99));
assertEquals(Optional.empty(), node.shortValueOpt());
}
private void _assertFailShortValueForFraction(JsonNode node) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.shortValue(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("cannot convert value")
.contains("to `short`: value has fractional part");
// assert defaulting
assertEquals(99, node.shortValue((short) 99));
assertEquals(Optional.empty(), node.shortValueOpt());
}
private void _assertFailShortForNonNumber(JsonNode node) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.shortValue(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("cannot convert value")
.contains("value type not numeric");
// assert defaulting
assertEquals(99, node.shortValue((short) 99));
assertEquals(Optional.empty(), node.shortValueOpt());
}
// // // Shared helper methods: asShort()
private void _assertAsShort(short expected, JsonNode node) {
assertEquals(expected, node.asShort());
// and defaulting
assertEquals(expected, node.asShort((short) 99));
assertEquals(expected, node.asShortOpt().get());
}
private void _assertAsShortFailForValueRange(JsonNode node) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.asShort(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("asShort()")
.contains("cannot convert value")
.contains("value not in 16-bit `short` range");
// assert defaulting
assertEquals(99, node.asShort((short) 99));
assertFalse(node.asShortOpt().isPresent());
}
private void _assertAsShortFailForNonNumber(JsonNode node) {
_assertAsShortFailForNonNumber(node, "value type not numeric");
}
private void _assertAsShortFailForNonNumber(JsonNode node, String extraFailMsg) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.asShort(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("asShort()")
.contains("cannot convert value")
.contains(extraFailMsg);
// assert defaulting
assertEquals(99, node.asShort((short) 99));
assertFalse(node.asShortOpt().isPresent());
}
private void _assertAsShortFailForNaN(JsonNode node) {
Exception e = assertThrows(JsonNodeException.class,
() -> node.asShort(),
"For ("+node.getClass().getSimpleName()+") value: "+node);
assertThat(e.getMessage())
.contains("asShort()")
.contains("cannot convert value")
.contains("value non-Finite");
// Verify default value handling
assertEquals(99, node.asShort((short) 99));
assertFalse(node.asShortOpt().isPresent());
}
}