All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ee.jakarta.tck.jsonp.api.jsonvaluetests.Structure Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2020, 2022 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 ee.jakarta.tck.jsonp.api.jsonvaluetests;

import ee.jakarta.tck.jsonp.api.common.JsonAssert;
import ee.jakarta.tck.jsonp.api.common.PointerRFCObject;
import ee.jakarta.tck.jsonp.api.common.SimpleValues;
import ee.jakarta.tck.jsonp.api.common.TestResult;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
import jakarta.json.JsonStructure;
import jakarta.json.JsonValue;

import java.util.logging.Logger;

// $Id$
/**
 * JavaScript Object Notation (JSON) compatibility tests for
 * {@link JsonStructure}. RFC 6901 JSON Pointer is being passed to
 * {@code JsonValue getValue(String)} method so whole JSON Pointer resolving
 * sample is being used to test this method.
 */
public class Structure {

  private static final Logger LOGGER = Logger.getLogger(Structure.class.getName());

  /**
   * Creates an instance of JavaScript Object Notation (JSON) compatibility
   * tests for {@link JsonStructure}.
   */
  Structure() {
    super();
  }

  /**
   * {@link JsonStructure} API methods added in JSON-P 1.1.
   * 
   * @return Result of all tests in this suite.
   */
  TestResult test() {
    final TestResult result = new TestResult(
        "JsonStructure API methods added in JSON-P 1.1.");
    LOGGER.info("JsonStructure API methods added in JSON-P 1.1.");
    testResolveWholeDocument(result);
    testResolveEmptyName(result);
    testResolveSimpleArray(result);
    testResolveSimpleArrayItems(result);
    testResolvePathWithEncodedSlash(result);
    testResolvePathWithSlash(result);
    testResolvePathWithPercent(result);
    testResolvePathWithCaret(result);
    testResolvePathWithVerticalBar(result);
    testResolvePathWithBackSlash(result);
    testResolvePathWithDoubleQuotes(result);
    testResolvePathWithSpace(result);
    testResolvePathWithTilde(result);
    testResolvePathWithEncodedTilde(result);
    testResolvePathWithEncodedTildeOne(result);
    testResolveValidNumericIndexInArray(result);
    testResolveMemberAfterLastInArray(result);
    testResolveNonNumericIndexInArray(result);
    return result;
  }

  /**
   * Test RFC 6901 JSON Pointer resolving for the whole document path using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolveWholeDocument(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = value;
    verifyGetValue(result, check, value, PointerRFCObject.RFC_KEY_WHOLE);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "": 0} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolveEmptyName(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL2);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR2);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolveSimpleArray(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = PointerRFCObject.RFC_VAL1;
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR1);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]} array
   * elements using {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolveSimpleArrayItems(final TestResult result) {
    final String[] itemPtrs = new String[] { PointerRFCObject.RFC_PTR1_ITEM1, PointerRFCObject.RFC_PTR1_ITEM2 };
    final String[] itemVals = new String[] { PointerRFCObject.RFC_VAL1_ITEM1, PointerRFCObject.RFC_VAL1_ITEM2 };
    final JsonObject value = PointerRFCObject.createRFC6901Object();
    for (int i = 0; i < itemPtrs.length; i++) {
      final JsonValue check = Json.createValue(itemVals[i]);
      verifyGetValue(result, check, value, itemPtrs[i]);
    }
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1} using
   * {@code JsonValue getValue(String)}. Character {@code '/'} is encoded as
   * {@code "~1"} string.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithEncodedSlash(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL3);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR3_ENC);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1} using
   * {@code JsonValue getValue(String)}. Character {@code '/'} is not encoded as
   * {@code "~1"} string. This results in invalid {@code "/a/b"} path and
   * resolving such path must throw an exception.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithSlash(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    verifyGetValueFail(result, value, PointerRFCObject.RFC_PTR3);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "c%d": 2} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithPercent(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL4);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR4);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "e^f": 3} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithCaret(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL5);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR5);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "g|h": 4} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithVerticalBar(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL6);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR6);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "i\\j": 5} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithBackSlash(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL7);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR7);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "k\"l": 6} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithDoubleQuotes(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL8);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR8);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code " ": 7} using
   * {@code JsonValue getValue(String)}.
   * 
   * @param result
   *          Tests result record.
   */
  private void testResolvePathWithSpace(final TestResult result) {
    final JsonStructure value = PointerRFCObject.createRFC6901Object();
    final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL9);
    verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR9);
  }

  /**
   * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8} without encoding
   * using {@code JsonValue getValue(String)}. Passing this test is not
   * mandatory.
   * {@see RFC 6901: 3.
   * Syntax} defines JSON pointer grammar as:
* {@code json-pointer = *( "/" reference-token )}
* {@code reference-token = *( unescaped / escaped )}
* {@code unescaped = %x00-2E / %x30-7D / %x7F-10FFFF}
* {@code escaped = "~" ( "0" / "1" )}
* Characters {@code '/'} and {@code '~'} are excluded from {@code unescaped}. * But having {@code '~'} outside escape sequence may be acceptable. * * @param result * Tests result record. */ private void testResolvePathWithTilde(final TestResult result) { LOGGER.info(" - resolving of \"" + PointerRFCObject.RFC_PTR10 + "\" pointer (optional)"); final JsonStructure value = PointerRFCObject.createRFC6901Object(); final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL10); boolean noError = true; try { final JsonValue out = value.getValue(PointerRFCObject.RFC_PTR10); if (operationFailed(check, out)) { noError = false; LOGGER.info(" - Pointer \"" + PointerRFCObject.RFC_KEY10 + "\" did not return expected value"); } } catch (JsonException e) { noError = false; LOGGER.info(" - Expected exception: " + e.getMessage()); } if (noError) { LOGGER.info( " - Pointer resolving accepts '~' outside escape sequence"); } } /** * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8} using * {@code JsonValue getValue(String)}. Character {@code '~'} is encoded as * {@code "~0"} string. * * @param result * Tests result record. */ private void testResolvePathWithEncodedTilde(final TestResult result) { final JsonStructure value = PointerRFCObject.createRFC6901Object(); final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL10); verifyGetValue(result, check, value, PointerRFCObject.RFC_KEY10_ENC); } /** * Test RFC 6901 JSON Pointer resolver for {@code "o~1p": 9} using * {@code JsonValue getValue(String)}. String {@code "~1"} is encoded as * {@code "~01"} String. Proper encoded sequences transformation is described * in chapter: * {@code "the string '~01' correctly becomes '~1' after transformation"}. * * @param result * Tests result record. */ private void testResolvePathWithEncodedTildeOne(final TestResult result) { final JsonStructure value = PointerRFCObject.createRFC6901Object(); final JsonValue check = Json.createValue(PointerRFCObject.RFC_VAL11); verifyGetValue(result, check, value, PointerRFCObject.RFC_PTR11_ENC); } /** * Test RFC 6901 JSON Pointer resolver for existing numeric indexes of an * array. {@see RFC * 6901: 4. Evaluation} chapter:
* If the currently referenced value is a JSON array, the reference token MUST * contain either: *
    *
  • characters comprised of digits (see ABNF below; note that leading zeros * are not allowed) that represent an unsigned base-10 integer value, making * the new referenced value the array element with the zero-based index * identified by the token
  • *
*/ private void testResolveValidNumericIndexInArray(final TestResult result) { LOGGER.info( " - getValue(String) resolving of pointer containing existing numeric array index"); final JsonArray[] arraysIn = new JsonArray[] { SimpleValues.createSimpleStringArray5(), SimpleValues.createSimpleIntArray5(), SimpleValues.createSimpleBoolArray5(), SimpleValues.createSimpleObjectArray5() }; final JsonValue[] strings = new JsonValue[] { SimpleValues.toJsonValue(SimpleValues.STR_VALUE_1), SimpleValues.toJsonValue(SimpleValues.STR_VALUE_2), SimpleValues.toJsonValue(SimpleValues.STR_VALUE_3), SimpleValues.toJsonValue(SimpleValues.STR_VALUE_4), SimpleValues.toJsonValue(SimpleValues.STR_VALUE_5) }; final JsonValue[] ints = new JsonValue[] { SimpleValues.toJsonValue(SimpleValues.INT_VALUE_1), SimpleValues.toJsonValue(SimpleValues.INT_VALUE_2), SimpleValues.toJsonValue(SimpleValues.INT_VALUE_3), SimpleValues.toJsonValue(SimpleValues.INT_VALUE_4), SimpleValues.toJsonValue(SimpleValues.INT_VALUE_5) }; final JsonValue[] bools = new JsonValue[] { SimpleValues.toJsonValue(SimpleValues.BOOL_FALSE), SimpleValues.toJsonValue(SimpleValues.BOOL_TRUE), SimpleValues.toJsonValue(SimpleValues.BOOL_TRUE), SimpleValues.toJsonValue(SimpleValues.BOOL_FALSE), SimpleValues.toJsonValue(SimpleValues.BOOL_TRUE) }; final JsonValue[] objs = new JsonValue[] { SimpleValues.OBJ_VALUE_1, SimpleValues.OBJ_VALUE_2, SimpleValues.OBJ_VALUE_3, SimpleValues.OBJ_VALUE_4, SimpleValues.OBJ_VALUE_5 }; final JsonValue[][] checks = new JsonValue[][] { strings, ints, bools, objs }; // Go trough all array types for (int i = 0; i < arraysIn.length; i++) { // Go trough all valid indexes in arrays for (int j = 0; j < 5; j++) { final String path = "/" + Integer.toString(j); try { final JsonValue out = arraysIn[i].getValue(path); if (operationFailed(checks[i][j], out)) { result.fail("getValue(String)", "Failed for \"" + path + "\" path"); } } catch (JsonException e) { result.fail("getValue(String)", "Exception: " + e.getMessage()); } } } } /** * Test RFC 6901 JSON Pointer resolver for character {@code '-'} marking the * end of an array. * {@see RFC 6901: 4. * Evaluation} chapter:
* If the currently referenced value is a JSON array, the reference token MUST * contain either: *
    *
  • exactly the single character "-", making the new referenced value the * (nonexistent) member after the last array element
  • *
* Note that the use of the "-" character to index an array will always result * in such an error condition because by definition it refers to a nonexistent * array element. Thus, applications of JSON Pointer need to specify how that * character is to be handled, if it is to be useful. */ private void testResolveMemberAfterLastInArray(final TestResult result) { LOGGER.info(" - getValue(String) resolving of array \"/-\" pointer"); final JsonArray[] arraysIn = new JsonArray[] { SimpleValues.createEmptyArray(), SimpleValues.createStringArray(), SimpleValues.createSimpleIntArray5(), SimpleValues.createBoolArray2(), SimpleValues.createSimpleObjectArray5() }; for (int i = 0; i < arraysIn.length; i++) { try { arraysIn[i].getValue("/-"); result.fail("getValue(String)", "Call of getValue(String) on \"" + "/-" + "\" shall throw JsonException"); } catch (JsonException e) { LOGGER.info(" - Expected exception: " + e.getMessage()); } } } /** * Test RFC 6901 JSON Pointer resolver for invalid index containing non * numeric characters on array. * {@see RFC 6901: 4. * Evaluation} chapter:
* {@code array-index = %x30 / ( %x31-39 *(%x30-39) )} grammar rule prohibits * indexes with anything else than sequence of digits. Index {@code '-'} is * being checked in another tests. The only exception is path for whole * document ({@code ""}) which must return the whole array. */ private void testResolveNonNumericIndexInArray(final TestResult result) { LOGGER.info( " - getValue(String) resolving of pointer containing non numeric array index"); final JsonArray[] arraysIn = new JsonArray[] { SimpleValues.createEmptyArray(), SimpleValues.createStringArray(), SimpleValues.createSimpleIntArray5(), SimpleValues.createBoolArray2(), SimpleValues.createSimpleObjectArray5() }; final String[] typeNames = new String[] { "empty", "String", "int", "boolean", "JsonObject" }; final String wholeDocument = ""; final String[] paths = new String[] { "/", "/1a", "/b4", "/name" }; // Go trough all array types for (int i = 0; i < arraysIn.length; i++) { try { final JsonValue wholeOut = arraysIn[i].getValue(wholeDocument); if (operationFailed(wholeOut, arraysIn[i])) { result.fail("getValue(String)", "Failed for \"" + wholeDocument + "\" path on " + typeNames[i] + " array"); } } catch (JsonException e) { result.fail("getValue(String)", "Failed for \"" + wholeDocument + "\" path on " + typeNames[i] + " array: " + e.getMessage()); } for (int j = 0; j < paths.length; j++) { try { final JsonValue out = arraysIn[i].getValue(paths[j]); result.fail("getValue(String)", "Succeeded for \"" + paths[j] + "\" path on " + typeNames[i] + " array"); } catch (JsonException e) { // There are too many combinations to log them. } } } } /** * Test helper: Verify {@code JsonValue getValue(String)} for given JSON path. * * @param result * Tests result record. */ private void verifyGetValue(final TestResult result, final JsonValue check, final JsonStructure value, final String path) { LOGGER.info(" - getValue(String) resolving of \"" + path + "\" pointer"); try { final JsonValue out = value.getValue(path); if (operationFailed(check, out)) { result.fail("getValue(String)", "Failed for \"" + path + "\" path"); } } catch (JsonException e) { result.fail("getValue(String)", "Exception: " + e.getMessage()); } } /** * Test helper: Verify {@code JsonValue getValue(String)} for given JSON path. * * @param result * Tests result record. */ private void verifyGetValueFail(final TestResult result, final JsonStructure value, final String path) { LOGGER.info( " - getValue(String) resolving of invalid \"" + path + "\" pointer"); try { value.getValue(path); result.fail("getValue(String)", "Call of getValue(String) on \"" + path + "\" shall throw JsonException"); } catch (JsonException e) { LOGGER.info(" - Expected exception: " + e.getMessage()); } } /** * Operation result check. * * @param check * Expected modified JSON value. * @param out * Operation output. * @return Value of {@code true} if operation passed or {@code false} * otherwise. */ protected boolean operationFailed(final JsonValue check, final JsonValue out) { return out == null || !JsonAssert.assertEquals(check, out); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy