ExceptionsTest.java

package tools.jackson.core.unittest;

import java.io.StringWriter;

import org.junit.jupiter.api.Test;

import tools.jackson.core.JsonGenerator;
import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.core.ObjectReadContext;
import tools.jackson.core.ObjectWriteContext;
import tools.jackson.core.StreamReadFeature;
import tools.jackson.core.TokenStreamLocation;
import tools.jackson.core.exc.StreamReadException;
import tools.jackson.core.exc.StreamWriteException;
import tools.jackson.core.exc.UnexpectedEndOfInputException;
import tools.jackson.core.json.JsonFactory;

import static org.junit.jupiter.api.Assertions.*;

class ExceptionsTest
    extends JacksonCoreTestBase
{
    private final JsonFactory JSON_F = newStreamFactory();

    // For [core#10]
    @Test
    void originalMesssage()
    {
        final TokenStreamLocation loc = new TokenStreamLocation(null, -1L, 1, 1);
        StreamReadException exc = new StreamReadException(null, "Foobar", loc);
        String msg = exc.getMessage();
        String orig = exc.getOriginalMessage();
        assertEquals("Foobar", orig);
        assertTrue(msg.length() > orig.length());

        // and another
        StreamReadException exc2 = new StreamReadException((JsonParser) null, "Second",
                loc, exc);
        assertSame(exc, exc2.getCause());
        exc2.clearLocation();
        assertNull(exc2.getLocation());

        // and yet with null
        StreamReadException exc3 = new StreamReadException((JsonParser) null, null, exc);
        assertNull(exc3.getOriginalMessage());
        assertEquals("N/A\n at [No location information]", exc3.getMessage());
        assertTrue(exc3.toString().startsWith(StreamReadException.class.getName()+": N/A"));
    }

    // [core#198]
    @Test
    void accessToParser() throws Exception
    {
        JsonParser p = JSON_F.createParser(ObjectReadContext.empty(), "{}");
        assertToken(JsonToken.START_OBJECT, p.nextToken());
        StreamReadException e = new StreamReadException(p, "Test!");
        assertSame(p, e.processor());
        assertEquals("Test!", e.getOriginalMessage());
        TokenStreamLocation loc = e.getLocation();
        assertNotNull(loc);
        assertEquals(2, loc.getColumnNr());
        assertEquals(1, loc.getLineNr());
        p.close();
    }

    // [core#198]
    @Test
    void accessToGenerator() throws Exception
    {
        StringWriter w = new StringWriter();
        JsonGenerator g = JSON_F.createGenerator(ObjectWriteContext.empty(), w);
        g.writeStartObject();
        StreamWriteException e = new StreamWriteException(g, "Test!");
        assertSame(g, e.processor());
        assertEquals("Test!", e.getOriginalMessage());
        g.close();
    }

    // [core#281]: new eof exception
    @Test
    void eofExceptionsBytes() throws Exception {
        _testEofExceptions(MODE_INPUT_STREAM);
    }

    // [core#281]: new eof exception
    @Test
    void eofExceptionsChars() throws Exception {
        _testEofExceptions(MODE_READER);
    }

    private void _testEofExceptions(int mode) throws Exception
    {
        JsonParser p = createParser(JSON_F, mode, "[ ");
        assertToken(JsonToken.START_ARRAY, p.nextToken());
        try {
            p.nextToken();
            fail("Should get exception");
        } catch (UnexpectedEndOfInputException e) {
            verifyException(e, "close marker for Array");
        }
        p.close();

        p = createParser(JSON_F, mode, "{ \"foo\" : [ ] ");
        assertToken(JsonToken.START_OBJECT, p.nextToken());
        assertToken(JsonToken.PROPERTY_NAME, p.nextToken());
        assertToken(JsonToken.START_ARRAY, p.nextToken());
        assertToken(JsonToken.END_ARRAY, p.nextToken());
        try {
            p.nextToken();
            fail("Should get exception");
        } catch (UnexpectedEndOfInputException e) {
            verifyException(e, "close marker for Object");
        }
        p.close();

        p = createParser(JSON_F, mode, "{ \"fo");
        assertToken(JsonToken.START_OBJECT, p.nextToken());
        try {
            p.nextToken();
            fail("Should get exception");
        } catch (UnexpectedEndOfInputException e) {

            verifyException(e, "in property name");
            assertEquals(JsonToken.PROPERTY_NAME, e.getTokenBeingDecoded());
        }
        p.close();

        p = createParser(JSON_F, mode, "{ \"field\" : ");
        assertToken(JsonToken.START_OBJECT, p.nextToken());
        try {
            p.nextToken();
            fail("Should get exception");
        } catch (UnexpectedEndOfInputException e) {
            verifyException(e, "unexpected end-of-input");
            verifyException(e, "Object entries");
        }
        p.close();

        // any other cases we'd like to test?
    }

    @Test
    void contentSnippetWithOffset() throws Exception
    {
        final JsonFactory jsonF = streamFactoryBuilder()
                .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION)
                .build();

        final String json = a2q("{'k1':'v1'}\n[broken]\n");
        final byte[] jsonB = utf8Bytes(json);
        final int lfIndex = json.indexOf("\n");
        final int start = lfIndex+1;
        final int len = json.length() - start;

        try (JsonParser p = jsonF.createParser(ObjectReadContext.empty(), jsonB, start, len)) {
            // [core#1180]: error location now points to start of invalid token
            _testContentSnippetWithOffset(p, 2, "(byte[])\"[broken]\n\"");
        }

        final char[] jsonC = json.toCharArray();
        try (JsonParser p = jsonF.createParser(ObjectReadContext.empty(), jsonC, start, len)) {
            // [core#1180]: error location now points to start of invalid token
            _testContentSnippetWithOffset(p, 2, "(char[])\"[broken]\n\"");
        }

        try (JsonParser p = jsonF.createParser(ObjectReadContext.empty(), json.substring(start))) {
            // [core#1180]: error location now points to start of invalid token
            _testContentSnippetWithOffset(p, 2, "(String)\"[broken]\n\"");
        }
    }

    private void _testContentSnippetWithOffset(final JsonParser p,
            int expColumn, String expContent) throws Exception
    {
        assertToken(JsonToken.START_ARRAY, p.nextToken());
        try {
            p.nextToken();
            fail("Should not pass");
        } catch (StreamReadException e) {
            verifyException(e, "Unrecognized token 'broken'");
            TokenStreamLocation loc = e.getLocation();
            assertEquals(1, loc.getLineNr());
            assertEquals(expColumn, loc.getColumnNr());
            final String srcDesc = loc.sourceDescription();
            assertEquals(expContent, srcDesc);
        }
    }
}