ParserScopeMatchingTest.java
package com.fasterxml.jackson.core.read;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.exc.StreamReadException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
/**
* Set of basic unit tests for verifying that Array/Object scopes
* are properly matched.
*/
@SuppressWarnings("resource")
public class ParserScopeMatchingTest extends JUnit5TestBase
{
@Test
void unclosedArray() throws Exception
{
for (int mode : ALL_MODES) {
_testUnclosedArray(mode);
}
}
public void _testUnclosedArray(int mode) throws Exception
{
try (JsonParser p = createParser(mode, "[ 1, 2 ")) {
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(2, p.getIntValue());
try {
p.nextToken();
fail("Expected an exception for unclosed ARRAY (mode: " + mode + ")");
} catch (JsonParseException pe) {
verifyException(pe, "expected close marker for ARRAY");
}
}
}
@Test
void unclosedObject() throws Exception
{
for (int mode : ALL_MODES) {
_testUnclosedObject(mode);
}
}
private void _testUnclosedObject(int mode) throws Exception
{
try (JsonParser p = createParser(mode, "{ \"key\" : 3 ")) {
assertToken(JsonToken.START_OBJECT, p.nextToken());
assertToken(JsonToken.FIELD_NAME, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
try {
p.nextToken();
fail("Expected an exception for unclosed OBJECT (mode: " + mode + ")");
} catch (JsonParseException pe) {
verifyException(pe, "expected close marker for OBJECT");
}
}
}
@Test
void eofInName() throws Exception
{
for (int mode : ALL_MODES) {
_testEOFInName(mode);
}
}
public void _testEOFInName(int mode) throws Exception
{
final String JSON = "{ \"abcd";
try (JsonParser p = createParser(mode, JSON)) {
assertToken(JsonToken.START_OBJECT, p.nextToken());
try {
p.nextToken();
fail("Expected an exception for EOF");
} catch (JsonParseException pe) {
verifyException(pe, "Unexpected end-of-input");
} catch (IOException ie) {
// DataInput behaves bit differently
if (mode == MODE_DATA_INPUT) {
verifyException(ie, "end-of-input");
return;
}
}
}
}
@Test
void weirdToken() throws Exception
{
for (int mode : ALL_MODES) {
_testWeirdToken(mode);
}
}
private void _testWeirdToken(int mode) throws Exception
{
final String JSON = "[ nil ]";
JsonParser p = createParser(mode, JSON);
assertToken(JsonToken.START_ARRAY, p.nextToken());
try {
p.nextToken();
fail("Expected an exception for weird token");
} catch (JsonParseException pe) {
verifyException(pe, "Unrecognized token");
}
p.close();
}
@Test
void mismatchArrayToObject() throws Exception
{
for (int mode : ALL_MODES) {
_testMismatchArrayToObject(mode);
}
}
private void _testMismatchArrayToObject(int mode) throws Exception
{
final String JSON = "[ 1, 2 }";
JsonParser p = createParser(mode, JSON);
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
try {
p.nextToken();
fail("Expected an exception for incorrectly closed ARRAY");
} catch (JsonParseException pe) {
verifyException(pe, "Unexpected close marker '}': expected ']'");
}
p.close();
}
@Test
void mismatchObjectToArray() throws Exception
{
for (int mode : ALL_MODES) {
_testMismatchObjectToArray(mode);
}
}
private void _testMismatchObjectToArray(int mode) throws Exception
{
final String JSON = "{ ]";
JsonParser p = createParser(mode, JSON);
assertToken(JsonToken.START_OBJECT, p.nextToken());
try {
p.nextToken();
fail("Expected an exception for incorrectly closed OBJECT");
} catch (JsonParseException pe) {
verifyException(pe, "Unexpected close marker ']': expected '}'");
}
p.close();
}
@Test
void misssingColon() throws Exception
{
for (int mode : ALL_MODES) {
_testMisssingColon(mode);
}
}
private void _testMisssingColon(int mode) throws Exception
{
final String JSON = "{ \"a\" \"b\" }";
JsonParser p = createParser(mode, JSON);
assertToken(JsonToken.START_OBJECT, p.nextToken());
try {
// can be either here, or with next one...
assertToken(JsonToken.FIELD_NAME, p.nextToken());
p.nextToken();
fail("Expected an exception for missing semicolon");
} catch (JsonParseException pe) {
verifyException(pe, "was expecting a colon");
}
p.close();
}
// [core#1394]
@Test
void extraEndArray() throws Exception
{
for (int mode : ALL_MODES) {
_extraEndArray(mode);
}
}
public void _extraEndArray(int mode) throws Exception
{
try (JsonParser p = createParser(mode, "{ }]")) {
assertToken(JsonToken.START_OBJECT, p.nextToken());
assertToken(JsonToken.END_OBJECT, p.nextToken());
try {
p.nextToken();
fail("Should have thrown an exception");
} catch (StreamReadException e) {
verifyException(e, "Unexpected close marker ']': no open Array");
}
}
}
// [core#1394]
@Test
void extraEndObject() throws Exception
{
for (int mode : ALL_MODES) {
_extraEndObject(mode);
}
}
public void _extraEndObject(int mode) throws Exception
{
try (JsonParser p = createParser(mode, "[ ]}")) {
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.END_ARRAY, p.nextToken());
try {
p.nextToken();
fail("Should have thrown an exception");
} catch (StreamReadException e) {
verifyException(e, "Unexpected close marker '}': no open Object");
}
}
}
}