From c1a42cbf1eaa8eccf0635afb401e648b1563e452 Mon Sep 17 00:00:00 2001 From: Anton Pinsky Date: Mon, 13 Nov 2023 23:43:44 +0100 Subject: [PATCH] [#112]Corrected skip methods behavior of JsonParserImpl; created test for these methods Signed-off-by: Anton Pinsky --- .gitignore | 1 + .../org/eclipse/parsson/JsonParserImpl.java | 143 +++++++++--------- .../eclipse/parsson/JsonParserFixture.java | 73 +++++++++ .../parsson/tests/JsonParserSkipTest.java | 134 +++++++++++----- 4 files changed, 244 insertions(+), 107 deletions(-) create mode 100644 impl/src/test/java/org/eclipse/parsson/JsonParserFixture.java diff --git a/.gitignore b/.gitignore index c8dfb82e..fdf8d269 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ nbproject/ *err_pid*.log /tck-impl/.gradle/ /tck-impl/build/ +/.sdkmanrc diff --git a/impl/src/main/java/org/eclipse/parsson/JsonParserImpl.java b/impl/src/main/java/org/eclipse/parsson/JsonParserImpl.java index 217af798..aa43eb43 100644 --- a/impl/src/main/java/org/eclipse/parsson/JsonParserImpl.java +++ b/impl/src/main/java/org/eclipse/parsson/JsonParserImpl.java @@ -189,26 +189,27 @@ public Stream getArrayStream() { JsonMessages.PARSER_GETARRAY_ERR(currentEvent)); } Spliterator spliterator = - new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) { - @Override - public Spliterator trySplit() { - return null; - } - @Override - public boolean tryAdvance(Consumer action) { - if (action == null) { - throw new NullPointerException(); - } - if (! hasNext()) { - return false; - } - if (next() == JsonParser.Event.END_ARRAY) { - return false; - } - action.accept(getValue()); - return true; - } - }; + new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public boolean tryAdvance(Consumer action) { + if (action == null) { + throw new NullPointerException(); + } + if (!hasNext()) { + return false; + } + if (next() == JsonParser.Event.END_ARRAY) { + return false; + } + action.accept(getValue()); + return true; + } + }; return StreamSupport.stream(spliterator, false); } @@ -219,36 +220,37 @@ public Stream> getObjectStream() { JsonMessages.PARSER_GETOBJECT_ERR(currentEvent)); } Spliterator> spliterator = - new Spliterators.AbstractSpliterator>(Long.MAX_VALUE, Spliterator.ORDERED) { - @Override - public Spliterator> trySplit() { - return null; - } - @Override - public boolean tryAdvance(Consumer> action) { - if (action == null) { - throw new NullPointerException(); - } - if (! hasNext()) { - return false; - } - JsonParser.Event e = next(); - if (e == JsonParser.Event.END_OBJECT) { - return false; - } - if (e != JsonParser.Event.KEY_NAME) { - throw new JsonException(JsonMessages.INTERNAL_ERROR()); - } - String key = getString(); - if (! hasNext()) { - throw new JsonException(JsonMessages.INTERNAL_ERROR()); - } - next(); - JsonValue value = getValue(); - action.accept(new AbstractMap.SimpleImmutableEntry<>(key, value)); - return true; - } - }; + new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator> trySplit() { + return null; + } + + @Override + public boolean tryAdvance(Consumer> action) { + if (action == null) { + throw new NullPointerException(); + } + if (!hasNext()) { + return false; + } + JsonParser.Event e = next(); + if (e == JsonParser.Event.END_OBJECT) { + return false; + } + if (e != JsonParser.Event.KEY_NAME) { + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + String key = getString(); + if (!hasNext()) { + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + next(); + JsonValue value = getValue(); + action.accept(new AbstractMap.SimpleImmutableEntry<>(key, value)); + return true; + } + }; return StreamSupport.stream(spliterator, false); } @@ -259,30 +261,31 @@ public Stream getValueStream() { JsonMessages.PARSER_GETVALUESTREAM_ERR()); } Spliterator spliterator = - new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) { - @Override - public Spliterator trySplit() { - return null; - } - @Override - public boolean tryAdvance(Consumer action) { - if (action == null) { - throw new NullPointerException(); - } - if (! hasNext()) { - return false; - } - next(); - action.accept(getValue()); - return true; - } - }; + new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public boolean tryAdvance(Consumer action) { + if (action == null) { + throw new NullPointerException(); + } + if (!hasNext()) { + return false; + } + next(); + action.accept(getValue()); + return true; + } + }; return StreamSupport.stream(spliterator, false); } @Override public void skipArray() { - if (currentEvent == Event.START_ARRAY) { + if (currentContext instanceof ArrayContext) { currentContext.skip(); currentContext = stack.pop(); currentEvent = Event.END_ARRAY; @@ -291,7 +294,7 @@ public void skipArray() { @Override public void skipObject() { - if (currentEvent == Event.START_OBJECT) { + if (currentContext instanceof ObjectContext) { currentContext.skip(); currentContext = stack.pop(); currentEvent = Event.END_OBJECT; diff --git a/impl/src/test/java/org/eclipse/parsson/JsonParserFixture.java b/impl/src/test/java/org/eclipse/parsson/JsonParserFixture.java new file mode 100644 index 00000000..3642ec38 --- /dev/null +++ b/impl/src/test/java/org/eclipse/parsson/JsonParserFixture.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.eclipse.parsson; + +import java.io.StringReader; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.stream.JsonParser; + +/** + * Class with methods that creates JsonParser with different configuration from different sources and runs the test code with this parser + */ +public class JsonParserFixture { + /** + * Runs the test code with JsonParser created from the given JsonObject + * + * @param object JsonObject to create JsonParser from + * @param parserConsumer test code to run with the created JsonParser + */ + public static void testWithCreateParserFromObject(JsonObject object, Consumer parserConsumer) { + testWithParser(() -> Json.createParserFactory(null).createParser(object), parserConsumer); + } + + /** + * Runs the test code with JsonParser created from the given JsonArray + * + * @param array JsonArray to create JsonParser from + * @param parserConsumer test code to run with the created JsonParser + */ + public static void testWithCreateParserFromArray(JsonArray array, Consumer parserConsumer) { + testWithParser(() -> Json.createParserFactory(null).createParser(array), parserConsumer); + } + + /** + * Runs the test code with JsonParser created from the given String + * + * @param string String with JSON to create JsonParser from + * @param parserConsumer test code to run with the created JsonParser + */ + public static void testWithCreateParserFromString(String string, Consumer parserConsumer) { + testWithParser(() -> Json.createParser(new StringReader(string)), parserConsumer); + } + + /** + * Runs the test code with JsonParser created from the given String + * + * @param parserSupplier Supplier of JsonParser to create JsonParser from + * @param parserConsumer test code to run with the created JsonParser + */ + private static void testWithParser(Supplier parserSupplier, Consumer parserConsumer) { + try (JsonParser parser = parserSupplier.get()) { + parserConsumer.accept(parser); + } + } +} diff --git a/impl/src/test/java/org/eclipse/parsson/tests/JsonParserSkipTest.java b/impl/src/test/java/org/eclipse/parsson/tests/JsonParserSkipTest.java index 56ea6af0..f138cb13 100644 --- a/impl/src/test/java/org/eclipse/parsson/tests/JsonParserSkipTest.java +++ b/impl/src/test/java/org/eclipse/parsson/tests/JsonParserSkipTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,13 +16,13 @@ package org.eclipse.parsson.tests; -import java.io.StringReader; import jakarta.json.Json; import jakarta.json.stream.JsonParser; import junit.framework.TestCase; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertTrue; + +import static org.eclipse.parsson.JsonParserFixture.testWithCreateParserFromArray; +import static org.eclipse.parsson.JsonParserFixture.testWithCreateParserFromObject; +import static org.eclipse.parsson.JsonParserFixture.testWithCreateParserFromString; /** * @@ -31,44 +31,70 @@ public class JsonParserSkipTest extends TestCase { public void testSkipArrayReader() { - try (JsonParser parser = Json.createParser(new StringReader("[[],[[]]]"))) { - testSkipArray(parser); - } + testWithCreateParserFromString("[[],[[]]]", JsonParserSkipTest::testSkipArray); } public void testSkipArrayStructure() { - try (JsonParser parser = Json.createParserFactory(null).createParser( - Json.createArrayBuilder() - .add(Json.createArrayBuilder()) - .add(Json.createArrayBuilder() - .add(Json.createArrayBuilder())) - .build())) { - testSkipArray(parser); - } + testWithCreateParserFromArray(Json.createArrayBuilder() + .add(Json.createArrayBuilder()) + .add(Json.createArrayBuilder() + .add(Json.createArrayBuilder())) + .build(), JsonParserSkipTest::testSkipArray); } private static void testSkipArray(JsonParser parser) { assertEquals(JsonParser.Event.START_ARRAY, parser.next()); parser.skipArray(); - assertEquals(false, parser.hasNext()); + assertFalse(parser.hasNext()); + } + + public void testSkipInsideArrayReader() { + testWithCreateParserFromString("[\"test\"]", JsonParserSkipTest::testSkipInsideArray); + } + + public void testSkipInsideArrayStructure() { + testWithCreateParserFromArray(Json.createArrayBuilder() + .add("test") + .build(), JsonParserSkipTest::testSkipInsideArray); + } + + private static void testSkipInsideArray(JsonParser parser) { + assertEquals(JsonParser.Event.START_ARRAY, parser.next()); + assertEquals(JsonParser.Event.VALUE_STRING, parser.next()); + parser.skipArray(); + assertFalse(parser.hasNext()); + } + + public void testNoSkipArrayReader() { + testWithCreateParserFromString("{\"key\":\"value\"}", JsonParserSkipTest::testNoSkipArray); + } + + public void testNoSkipArrayStructure() { + testWithCreateParserFromObject(Json.createObjectBuilder() + .add("key","value") + .build(), JsonParserSkipTest::testNoSkipArray); + } + + private static void testNoSkipArray(JsonParser parser) { + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + parser.skipArray(); + assertEquals(JsonParser.Event.VALUE_STRING, parser.next()); + assertEquals(JsonParser.Event.END_OBJECT, parser.next()); + assertFalse(parser.hasNext()); } public void testSkipArrayInObjectReader() { - try (JsonParser parser = Json.createParser(new StringReader("{\"array\":[[],[[]]],\"object\":\"value2\"}"))) { - testSkipArrayInObject(parser); - } + testWithCreateParserFromString("{\"array\":[[],[[]]],\"object\":\"value2\"}", JsonParserSkipTest::testSkipArrayInObject); } public void testSkipArrayInObjectStructure() { - try (JsonParser parser = Json.createParserFactory(null).createParser( - Json.createObjectBuilder().add("array", Json.createArrayBuilder() + testWithCreateParserFromObject(Json.createObjectBuilder().add("array", Json.createArrayBuilder() .add(Json.createArrayBuilder()) .add(Json.createArrayBuilder() .add(Json.createArrayBuilder())) ).add("object", "value2") - .build())) { - testSkipArrayInObject(parser); - } + .build(), JsonParserSkipTest::testSkipArrayInObject); } private static void testSkipArrayInObject(JsonParser parser) { @@ -84,20 +110,15 @@ private static void testSkipArrayInObject(JsonParser parser) { } public void testSkipObjectReader() { - try (JsonParser parser = Json.createParser(new StringReader("{\"array\":[],\"objectToSkip\":{\"huge key\":\"huge value\"},\"simple\":2}"))) { - testSkipObject(parser); - } + testWithCreateParserFromString("{\"array\":[],\"objectToSkip\":{\"huge key\":\"huge value\"},\"simple\":2}", JsonParserSkipTest::testSkipObject); } public void testSkipObjectStructure() { - try (JsonParser parser = Json.createParserFactory(null).createParser( - Json.createObjectBuilder() - .add("array", Json.createArrayBuilder().build()) - .add("objectToSkip", Json.createObjectBuilder().add("huge key", "huge value")) - .add("simple", 2) - .build())) { - testSkipObject(parser); - } + testWithCreateParserFromObject(Json.createObjectBuilder() + .add("array", Json.createArrayBuilder().build()) + .add("objectToSkip", Json.createObjectBuilder().add("huge key", "huge value")) + .add("simple", 2) + .build(), JsonParserSkipTest::testSkipObject); } private static void testSkipObject(JsonParser parser) { @@ -111,6 +132,45 @@ private static void testSkipObject(JsonParser parser) { assertEquals(JsonParser.Event.KEY_NAME, parser.next()); assertEquals(JsonParser.Event.VALUE_NUMBER, parser.next()); assertEquals(JsonParser.Event.END_OBJECT, parser.next()); - assertEquals(false, parser.hasNext()); + assertFalse(parser.hasNext()); + } + + public void testSkipInsideObjectReader() { + testWithCreateParserFromString("{\"objectToSkip\":{\"huge key\":\"huge value\"},\"simple\":2}", JsonParserSkipTest::testSkipInsideObject); + } + + public void testSkipInsideObjectStructure() { + testWithCreateParserFromObject(Json.createObjectBuilder() + .add("objectToSkip", Json.createObjectBuilder().add("huge key", "huge value")) + .add("simple", 2) + .build(), JsonParserSkipTest::testSkipInsideObject); + } + + private static void testSkipInsideObject(JsonParser parser) { + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + parser.skipObject(); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.VALUE_NUMBER, parser.next()); + assertEquals(JsonParser.Event.END_OBJECT, parser.next()); + assertFalse(parser.hasNext()); + } + + public void testNoSkipObjectReader() { + testWithCreateParserFromString("{\"key\":\"value\"}", JsonParserSkipTest::testNoSkipObject); + } + + public void testNoSkipObjectStructure() { + testWithCreateParserFromObject(Json.createObjectBuilder() + .add("Key", "value") + .build(), JsonParserSkipTest::testNoSkipObject); + } + + private static void testNoSkipObject(JsonParser parser) { + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + parser.skipObject(); + assertFalse(parser.hasNext()); } }