JsonDecoderTest.java
package zserio.runtime.json;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.math.BigInteger;
import org.junit.jupiter.api.Test;
public class JsonDecoderTest
{
@Test
public void decodeNull()
{
checkDecoderSuccess("null", 0, 4, null);
checkDecoderSuccess("{ } null", 4, 4, null);
checkDecoderSuccess("null { }", 0, 4, null);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("invalid", 1, 4);
checkDecoderFailure("nul", 0, 3);
}
@Test
public void decodeTrue()
{
checkDecoderSuccess("true", 0, 4, true);
checkDecoderSuccess("{ } true", 4, 4, true);
checkDecoderSuccess("true { }", 0, 4, true);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("stainless", 1, 4);
checkDecoderFailure("tru", 0, 3);
}
@Test
public void decodeFalse()
{
checkDecoderSuccess("false", 0, 5, false);
checkDecoderSuccess("{ } false", 4, 5, false);
checkDecoderSuccess("false { }", 0, 5, false);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("affected", 1, 5);
checkDecoderFailure("fal", 0, 3);
}
@Test
public void decodeNan()
{
checkDecoderSuccess("NaN", 0, 3, Double.NaN);
checkDecoderSuccess("{ } NaN", 4, 3, Double.NaN);
checkDecoderSuccess("NaN { }", 0, 3, Double.NaN);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("iNactive", 1, 3);
checkDecoderFailure("Na", 0, 2);
}
@Test
public void decodePositiveInfinity()
{
checkDecoderSuccess("Infinity", 0, 8, Double.POSITIVE_INFINITY);
checkDecoderSuccess("{ } Infinity", 4, 8, Double.POSITIVE_INFINITY);
checkDecoderSuccess("Infinity { }", 0, 8, Double.POSITIVE_INFINITY);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("iInfinvalid", 1, 8);
checkDecoderFailure("Infin", 0, 5);
}
@Test
public void decodeNegativeInfinity()
{
checkDecoderSuccess("-Infinity", 0, 9, Double.NEGATIVE_INFINITY);
checkDecoderSuccess("{ } -Infinity", 4, 9, Double.NEGATIVE_INFINITY);
checkDecoderSuccess("-Infinity { }", 0, 9, Double.NEGATIVE_INFINITY);
checkDecoderFailure("invalid", 0, 1);
checkDecoderFailure("i-Infinvalid", 1, 9);
checkDecoderFailure("-Infin", 0, 6);
checkDecoderFailure("-Infix", 0, 6);
}
@Test
public void decodeSignedIntegral()
{
checkDecoderSuccess("-0", 0, 2, BigInteger.ZERO);
checkDecoderSuccess("{ } -0", 4, 2, BigInteger.ZERO);
checkDecoderSuccess("-0 { }", 0, 2, BigInteger.ZERO);
checkDecoderSuccess("-1", 0, 2, BigInteger.valueOf(-1));
checkDecoderSuccess("-9223372036854775808", 0, 20, BigInteger.valueOf(Long.MIN_VALUE));
checkDecoderFailure("--10", 0, 1);
checkDecoderFailure("-", 0, 1);
}
@Test
public void decodeUnsignedIntegral()
{
checkDecoderSuccess("0", 0, 1, BigInteger.ZERO);
checkDecoderSuccess("{ } 0", 4, 1, BigInteger.ZERO);
checkDecoderSuccess("0 { }", 0, 1, BigInteger.ZERO);
checkDecoderSuccess("1", 0, 1, BigInteger.ONE);
checkDecoderSuccess("9223372036854775807", 0, 19, BigInteger.valueOf(Long.MAX_VALUE));
checkDecoderSuccess("18446744073709551615", 0, 20, new BigInteger("18446744073709551615"));
checkDecoderFailure("+10", 0, 1);
}
@Test
public void decodeDouble()
{
checkDecoderSuccess("0.0", 0, 3, 0.0);
checkDecoderSuccess("{ } 0.0", 4, 3, 0.0);
checkDecoderSuccess("0.0 { }", 0, 3, 0.0);
checkDecoderSuccess("-1.0", 0, 4, -1.0);
checkDecoderSuccess("1.0", 0, 3, 1.0);
checkDecoderSuccess("3.5", 0, 3, 3.5);
checkDecoderSuccess("9.875", 0, 5, 9.875);
checkDecoderSuccess("0.6171875", 0, 9, 0.6171875);
checkDecoderSuccess("1e+20", 0, 5, 1e+20);
checkDecoderSuccess("1E+20", 0, 5, 1E+20);
checkDecoderSuccess("1e-20", 0, 5, 1e-20);
checkDecoderSuccess("1E-20", 0, 5, 1E-20);
checkDecoderSuccess("-1e+20", 0, 6, -1e+20);
checkDecoderSuccess("-1E+20", 0, 6, -1E+20);
checkDecoderSuccess("-1e-20", 0, 6, -1e-20);
checkDecoderSuccess("-1E-20", 0, 6, -1E-20);
checkDecoderSuccess("1.0E-20", 0, 7, 1.0E-20);
checkDecoderSuccess("-1.0E-20", 0, 8, -1.0E-20);
checkDecoderSuccess("9.875E+3", 0, 8, 9.875E+3);
checkDecoderSuccess("-9.875E-3", 0, 9, -9.875E-3);
checkDecoderFailure("1EE20", 0, 2);
checkDecoderFailure("1E.E20", 0, 2);
checkDecoderFailure("1E++20", 0, 3);
checkDecoderFailure("1E--20", 0, 3);
checkDecoderFailure("1e", 0, 2);
checkDecoderFailure("1e+", 0, 3);
checkDecoderFailure("1E-", 0, 3);
}
@Test
public void decodeString()
{
checkDecoderSuccess("\"\"", 0, 2, "");
checkDecoderSuccess("{ } \"\"", 4, 2, "");
checkDecoderSuccess("\"\" { }", 0, 2, "");
checkDecoderSuccess("\"test\"", 0, 6, "test");
checkDecoderSuccess("\"München\"", 0, 9, "München");
checkDecoderSuccess("\"€\"", 0, 3, "€");
// escapes
checkDecoderSuccess("\"\\\\\"", 0, 4, "\\");
checkDecoderSuccess("\"\\\"\"", 0, 4, "\"");
checkDecoderSuccess("\"\\b\"", 0, 4, "\b");
checkDecoderSuccess("\"\\f\"", 0, 4, "\f");
checkDecoderSuccess("\"\\n\"", 0, 4, "\n");
checkDecoderSuccess("\"\\r\"", 0, 4, "\r");
checkDecoderSuccess("\"\\t\"", 0, 4, "\t");
checkDecoderSuccess("\"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\\"'Hello World2\"", 0, 62,
"\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"\'Hello World2");
// <= 0x1F -> unicode escape
checkDecoderSuccess("\"\\u001f\"", 0, 8, "\u001f");
checkDecoderFailure("\"\\u001x\"", 0, 7);
checkDecoderFailure("\"unterminated", 0, 13);
checkDecoderFailure("\"wrong escape \\", 0, 15);
checkDecoderFailure("\"wrong unicode escape \\u0", 0, 25);
checkDecoderFailure("\"unknown escape \\x", 0, 18);
}
@Test
public void wrong_arguments()
{
checkDecoderFailure("", 1, 0);
}
private void checkDecoderSuccess(String input, int pos, int expectedNumRead, Object expectedValue)
{
final JsonDecoder.Result result = JsonDecoder.decodeValue(input, pos);
assertEquals(true, result.success());
assertEquals(expectedValue, result.getValue());
assertEquals(expectedNumRead, result.getNumReadChars());
}
private void checkDecoderFailure(String input, int pos, int expectedNumRead)
{
final JsonDecoder.Result result = JsonDecoder.decodeValue(input, pos);
assertEquals(false, result.success());
assertEquals(null, result.getValue());
assertEquals(expectedNumRead, result.getNumReadChars());
}
}