From fc73bee380444112e9294545d4f0b66094884dab Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 18 Sep 2019 18:35:41 -0700 Subject: [PATCH] Fix #563 (async parser, location for array values) --- release-notes/CREDITS-2.x | 2 +- release-notes/VERSION-2.x | 5 ++-- .../json/async/NonBlockingJsonParser.java | 3 +++ .../AsyncPointerFromContext563Test.java | 24 +++++++++++++++---- .../core/testsupport/AsyncReaderWrapper.java | 5 ++++ 5 files changed, 31 insertions(+), 8 deletions(-) rename src/test/java/com/fasterxml/jackson/{failing => core/json/async}/AsyncPointerFromContext563Test.java (86%) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 15a55437f4..0e6ebe1341 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -155,7 +155,7 @@ Doug Roper (htmldoug@github) * Suggested #463: Ensure that `skipChildren()` of non-blocking `JsonParser` will throw exception if not enough input (2.9.6) - * Contributed test for #563: Async parser does not keep track of Array context properly + * Reported, Contributed test for #563: Async parser does not keep track of Array context properly (2.10.0) Alexander Eyers-Taylor (aeyerstaylor@github) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index b4a90f8a9b..65eeb3be58 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -16,9 +16,10 @@ JSON library. 2.10.0.pr3 (16-Sep-2019) -#479: Improve thread-safety of buffer recycling to enable recycling again - for async parsing +#479: Improve thread-safety of buffer recycling #561: Misleading exception for unquoted String parsing +#563: Async parser does not keep track of Array context properly + (reported by Doug R) 2.10.0.pr2 (31-Aug-2019) diff --git a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java index 03a5d76cb1..429fcf251c 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java @@ -602,6 +602,9 @@ private final JsonToken _startValue(int ch) throws IOException } } _updateTokenLocation(); + // 17-Sep-2019, tatu: [core#563] Need to call this to update index within array + _parsingContext.expectComma(); + if (ch == INT_QUOTE) { return _startString(); } diff --git a/src/test/java/com/fasterxml/jackson/failing/AsyncPointerFromContext563Test.java b/src/test/java/com/fasterxml/jackson/core/json/async/AsyncPointerFromContext563Test.java similarity index 86% rename from src/test/java/com/fasterxml/jackson/failing/AsyncPointerFromContext563Test.java rename to src/test/java/com/fasterxml/jackson/core/json/async/AsyncPointerFromContext563Test.java index 791a0a79da..e9006e2b72 100644 --- a/src/test/java/com/fasterxml/jackson/failing/AsyncPointerFromContext563Test.java +++ b/src/test/java/com/fasterxml/jackson/core/json/async/AsyncPointerFromContext563Test.java @@ -1,8 +1,8 @@ -package com.fasterxml.jackson.failing; +package com.fasterxml.jackson.core.json.async; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.async.AsyncTestBase; -import com.fasterxml.jackson.core.json.async.NonBlockingJsonParser; +import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper; public class AsyncPointerFromContext563Test extends AsyncTestBase { @@ -11,11 +11,23 @@ public class AsyncPointerFromContext563Test extends AsyncTestBase // [core#563] public void testPointerWithAsyncParser() throws Exception { - JsonParser p = JSON_F.createNonBlockingByteArrayParser(); final String SIMPLE = aposToQuotes("{'a':123,'array':[1,2,[3],5,{'obInArray':4}]," +"'ob':{'first':[false,true],'second':{'sub':37}},'b':true}"); byte[] SIMPLE_BYTES = SIMPLE.getBytes("UTF-8"); - ((NonBlockingJsonParser) p).feedInput(SIMPLE_BYTES, 0, SIMPLE_BYTES.length); + + _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 1000); + _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 7); + _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 3); + _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 2); + _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 1); + + _testPointerWithAsyncParser(SIMPLE_BYTES, 20, 5); + _testPointerWithAsyncParser(SIMPLE_BYTES, 14, 1); + } + + public void _testPointerWithAsyncParser(byte[] doc, int offset, int readSize) throws Exception + { + AsyncReaderWrapper p = asyncForBytes(JSON_F, readSize, doc, offset); // by default should just get "empty" assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer()); @@ -24,6 +36,8 @@ public void testPointerWithAsyncParser() throws Exception assertToken(JsonToken.START_OBJECT, p.nextToken()); assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer()); + assertEquals("", p.getParsingContext().pathAsPointer().toString()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); // a assertEquals("/a", p.getParsingContext().pathAsPointer().toString()); @@ -92,8 +106,8 @@ public void testPointerWithAsyncParser() throws Exception assertToken(JsonToken.END_OBJECT, p.nextToken()); assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer()); + // note: wrapper maps to `null`, plain async-parser would give NOT_AVAILABLE assertNull(p.nextToken()); p.close(); - } } diff --git a/src/test/java/com/fasterxml/jackson/core/testsupport/AsyncReaderWrapper.java b/src/test/java/com/fasterxml/jackson/core/testsupport/AsyncReaderWrapper.java index 084cb71610..7f817af876 100644 --- a/src/test/java/com/fasterxml/jackson/core/testsupport/AsyncReaderWrapper.java +++ b/src/test/java/com/fasterxml/jackson/core/testsupport/AsyncReaderWrapper.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser.NumberType; +import com.fasterxml.jackson.core.JsonStreamContext; import com.fasterxml.jackson.core.JsonToken; public abstract class AsyncReaderWrapper @@ -53,6 +54,10 @@ public String currentName() throws IOException { public abstract JsonToken nextToken() throws IOException; + public JsonStreamContext getParsingContext() { + return _streamReader.getParsingContext(); + } + public int getIntValue() throws IOException { return _streamReader.getIntValue(); } public long getLongValue() throws IOException { return _streamReader.getLongValue(); } public float getFloatValue() throws IOException { return _streamReader.getFloatValue(); }