blob: 85a5541e43f3b7bac08ed61ef8645025f473078f [file] [log] [blame]
package org.codehaus.jackson.main;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.codehaus.jackson.*;
/**
* Set of basic unit tests for verifying that the basic parser
* functionality works as expected.
*/
public class TestNumericValues
extends main.BaseTest
{
public void testSimpleInt()
throws Exception
{
int EXP_I = 1234;
JsonParser jp = createParserUsingReader("[ "+EXP_I+" ]");
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.INT, jp.getNumberType());
assertEquals(""+EXP_I, jp.getText());
assertEquals(EXP_I, jp.getIntValue());
assertEquals((long) EXP_I, jp.getLongValue());
assertEquals((double) EXP_I, jp.getDoubleValue());
assertEquals(BigDecimal.valueOf((long) EXP_I), jp.getDecimalValue());
}
public void testIntRange()
throws Exception
{
// let's test with readers and streams, separate code paths:
for (int i = 0; i < 2; ++i) {
String input = "[ "+Integer.MAX_VALUE+","+Integer.MIN_VALUE+" ]";
JsonParser jp;
if (i == 0) {
jp = createParserUsingReader(input);
} else {
jp = this.createParserUsingStream(input, "UTF-8");
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.INT, jp.getNumberType());
assertEquals(Integer.MAX_VALUE, jp.getIntValue());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.INT, jp.getNumberType());
assertEquals(Integer.MIN_VALUE, jp.getIntValue());
}
}
public void testInvalidIntAccess()
throws Exception
{
JsonParser jp = createParserUsingReader("[ \"abc\" ]");
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
try {
jp.getIntValue();
fail("Expected error trying to call getIntValue on non-numeric value");
} catch (JsonParseException e) {
verifyException(e, "can not use numeric value accessors");
}
}
public void testSimpleLong()
throws Exception
{
long EXP_L = 12345678907L;
JsonParser jp = createParserUsingReader("[ "+EXP_L+" ]");
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
// beyond int, should be long
assertEquals(JsonParser.NumberType.LONG, jp.getNumberType());
assertEquals(""+EXP_L, jp.getText());
assertEquals(EXP_L, jp.getLongValue());
// Should get an exception if trying to convert to int
try {
jp.getIntValue();
} catch (JsonParseException jpe) {
verifyException(jpe, "out of range");
}
assertEquals((double) EXP_L, jp.getDoubleValue());
assertEquals(BigDecimal.valueOf((long) EXP_L), jp.getDecimalValue());
}
public void testLongRange()
throws Exception
{
for (int i = 0; i < 2; ++i) {
long belowMinInt = -1L + Integer.MIN_VALUE;
long aboveMaxInt = 1L + Integer.MAX_VALUE;
String input = "[ "+Long.MAX_VALUE+","+Long.MIN_VALUE+","+aboveMaxInt+", "+belowMinInt+" ]";
JsonParser jp;
if (i == 0) {
jp = createParserUsingReader(input);
} else {
jp = this.createParserUsingStream(input, "UTF-8");
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.LONG, jp.getNumberType());
assertEquals(Long.MAX_VALUE, jp.getLongValue());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.LONG, jp.getNumberType());
assertEquals(Long.MIN_VALUE, jp.getLongValue());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.LONG, jp.getNumberType());
assertEquals(aboveMaxInt, jp.getLongValue());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.LONG, jp.getNumberType());
assertEquals(belowMinInt, jp.getLongValue());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
}
public void testBigDecimalRange()
throws Exception
{
for (int i = 0; i < 2; ++i) {
// let's test first values outside of Long range
BigInteger small = new BigDecimal(Long.MIN_VALUE).toBigInteger();
small = small.subtract(BigInteger.ONE);
BigInteger big = new BigDecimal(Long.MAX_VALUE).toBigInteger();
big = big.add(BigInteger.ONE);
String input = "[ "+small+" , "+big+"]";
JsonParser jp;
if (i == 0) {
jp = createParserUsingReader(input);
} else {
jp = this.createParserUsingStream(input, "UTF-8");
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.BIG_INTEGER, jp.getNumberType());
assertEquals(small, jp.getBigIntegerValue());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(JsonParser.NumberType.BIG_INTEGER, jp.getNumberType());
assertEquals(big, jp.getBigIntegerValue());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
}
public void testSimpleDouble()
throws Exception
{
final String[] INPUTS = new String[] {
"1234.00", "2.1101567E-16", "1.0e5", "2.5e+5", "9e4", "-12e-3", "0.25"
};
for (int input = 0; input < 2; ++input) {
for (int i = 0; i < INPUTS.length; ++i) {
/* Testing double is more difficult, given the rounding
* errors and such. But let's try anyways.
*/
String STR = INPUTS[i];
double EXP_D = Double.parseDouble(STR);
String DOC = "["+STR+"]";
JsonParser jp;
if (input == 0) {
jp = createParserUsingStream(DOC, "UTF-8");
} else {
jp = createParserUsingReader(DOC);
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertEquals(STR, jp.getText());
assertEquals(EXP_D, jp.getDoubleValue());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
}
}
public void testNumbers()
throws Exception
{
final String DOC = "[ -13, 8100200300, 13.5, 0.00010, -2.033 ]";
for (int input = 0; input < 2; ++input) {
JsonParser jp;
if (input == 0) {
jp = createParserUsingStream(DOC, "UTF-8");
} else {
jp = createParserUsingReader(DOC);
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(-13, jp.getIntValue());
assertEquals(-13L, jp.getLongValue());
assertEquals(-13., jp.getDoubleValue());
assertEquals("-13", jp.getText());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals(8100200300L, jp.getLongValue());
// Should get exception for overflow:
try {
/*int x =*/ jp.getIntValue();
fail("Expected an exception for overflow");
} catch (Exception e) {
verifyException(e, "out of range");
}
assertEquals(8100200300., jp.getDoubleValue());
assertEquals("8100200300", jp.getText());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertEquals(13, jp.getIntValue());
assertEquals(13L, jp.getLongValue());
assertEquals(13.5, jp.getDoubleValue());
assertEquals("13.5", jp.getText());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertEquals(0, jp.getIntValue());
assertEquals(0L, jp.getLongValue());
assertEquals(0.00010, jp.getDoubleValue());
assertEquals("0.00010", jp.getText());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertEquals(-2, jp.getIntValue());
assertEquals(-2L, jp.getLongValue());
assertEquals(-2.033, jp.getDoubleValue());
assertEquals("-2.033", jp.getText());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
}
}
public void testLongOverflow() throws Exception
{
BigInteger below = BigInteger.valueOf(Long.MIN_VALUE);
below = below.subtract(BigInteger.ONE);
BigInteger above = BigInteger.valueOf(Long.MAX_VALUE);
above = above.add(BigInteger.ONE);
String DOC_BELOW = below.toString() + " ";
String DOC_ABOVE = below.toString() + " ";
for (int input = 0; input < 2; ++input) {
JsonParser jp;
if (input == 0) {
jp = createParserUsingStream(DOC_BELOW, "UTF-8");
} else {
jp = createParserUsingReader(DOC_BELOW);
}
jp.nextToken();
try {
long x = jp.getLongValue();
fail("Expected an exception for underflow (input "+jp.getText()+"): instead, got long value: "+x);
} catch (JsonParseException e) {
verifyException(e, "out of range of long");
}
jp.close();
if (input == 0) {
jp = createParserUsingStream(DOC_ABOVE, "UTF-8");
} else {
jp = createParserUsingReader(DOC_ABOVE);
}
jp.nextToken();
try {
long x = jp.getLongValue();
fail("Expected an exception for underflow (input "+jp.getText()+"): instead, got long value: "+x);
} catch (JsonParseException e) {
verifyException(e, "out of range of long");
}
jp.close();
}
}
/**
* Method that tries to test that number parsing works in cases where
* input is split between buffer boundaries.
*/
public void testParsingOfLongerSequences()
throws Exception
{
double[] values = new double[] { 0.01, -10.5, 2.1e9, 4.0e-8 };
StringBuilder sb = new StringBuilder();
for (int i = 0; i < values.length; ++i) {
if (i > 0) {
sb.append(',');
}
sb.append(values[i]);
}
String segment = sb.toString();
int COUNT = 1000;
sb = new StringBuilder(COUNT * segment.length() + 20);
sb.append("[");
for (int i = 0; i < COUNT; ++i) {
if (i > 0) {
sb.append(',');
}
sb.append(segment);
sb.append('\n');
// let's add somewhat arbitray number of spaces
int x = (i & 3);
if (i > 300) {
x += i % 5;
}
while (--x > 0) {
sb.append(' ');
}
}
sb.append("]");
String DOC = sb.toString();
for (int input = 0; input < 2; ++input) {
JsonParser jp;
if (input == 0) {
jp = createParserUsingStream(DOC, "UTF-8");
} else {
jp = createParserUsingReader(DOC);
}
assertToken(JsonToken.START_ARRAY, jp.nextToken());
for (int i = 0; i < COUNT; ++i) {
for (double d : values) {
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertEquals(d, jp.getDoubleValue());
}
}
assertToken(JsonToken.END_ARRAY, jp.nextToken());
}
}
/*
/**********************************************************
/* New tests for 1.3 features
/**********************************************************
*/
public void testSimpleBoolean()
throws Exception
{
JsonParser jp = createParserUsingReader("[ true ]");
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
assertEquals(true, jp.getBooleanValue());
}
public void testInvalidBooleanAccess()
throws Exception
{
JsonParser jp = createParserUsingReader("[ \"abc\" ]");
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
try {
jp.getBooleanValue();
fail("Expected error trying to call getBooleanValue on non-boolean value");
} catch (JsonParseException e) {
verifyException(e, "not of boolean type");
}
}
}