You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by al...@apache.org on 2019/11/07 19:13:41 UTC

[asterixdb] branch master updated: [ASTERIXDB-2672][API] Change the valid values for "format" request parameter

This is an automated email from the ASF dual-hosted git repository.

alsuliman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 97557a8  [ASTERIXDB-2672][API] Change the valid values for "format" request parameter
97557a8 is described below

commit 97557a81bd4f1feee3d05e60148d89f5fa00f052
Author: Ali Alsuliman <al...@gmail.com>
AuthorDate: Tue Nov 5 14:09:17 2019 -0800

    [ASTERIXDB-2672][API] Change the valid values for "format" request parameter
    
    - user model changes: yes
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Allowed values for "format" request parameter: json, csv, adm.
    - Recognizable format values in "Accept":
      application/x-adm
      application/json
      application/json;lossless=true/false
      text/csv
      text/csv;header=present/absent
    
    Test framework changes:
    - ResultExtractor: if the OutputFormat is json/lossless-json, print the "result"
      field of the response similar to how adm would be printed, one json value
      per line (and using same spacing).
    - Changed some queries that use "EXPLAIN SELECT..." and specify OutputFormat as JSON.
      The queries extension is ".plans.sqlpp". "param optimized-logical-plan:string=true"
      is specified in those queries to print the logical plan in the "plans" field of
      the response.
    - added "// compareunorderedarray=true" for test quries that use .regexjson to compare
      one json value against another where the order of elements in a json array is not
      deterministic.
    - TestExecutor: OutputFormat.LOSSLESS_JSON & OutputFormat.CSV_HEADER formats are set
      in the "Accept". Otherwise, the desired format is set in the "format" request
      parameter as usual.
    - TestHelper: changed "equalJson()" to allow comparing json array in two modes.
    - Removed some test cases that used to set mime types in the "format" request parameter
      since now it's not allowed to do so.
    
    Change-Id: Ie3c7a35446322c2d97679e7e724b9778e2a4ba83
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4043
    Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Ali Alsuliman <al...@gmail.com>
    Reviewed-by: Murtadha Hubail <mh...@apache.org>
---
 .../translator/ExecutionPlansJsonPrintUtil.java    |   2 +-
 .../http/server/QueryServiceRequestParameters.java |   8 +-
 .../asterix/app/result/ResultPrinterTest.java      |   5 +-
 .../asterix/test/common/ResultExtractor.java       | 146 +++++++++++++++------
 .../apache/asterix/test/common/TestExecutor.java   | 132 ++++++++++++-------
 .../org/apache/asterix/test/common/TestHelper.java |  82 ++++++------
 .../asterix/test/sqlpp/ParserTestExecutor.java     |   2 +-
 .../request-param/request-param.003.query.sqlpp    |  24 ----
 .../request-param/request-param.004.query.sqlpp    |  24 ----
 .../request-param/request-param.005.query.sqlpp    |  24 ----
 .../request-param/request-param.006.query.sqlpp    |  24 ----
 .../request-param/request-param.007.query.sqlpp    |  24 ----
 .../request-param/request-param.008.query.sqlpp    |  24 ----
 .../profile/full-scan/full-scan.3.profile.sqlpp    |   2 +-
 .../api/request-param/request-param.001.json       |   3 +-
 .../api/request-param/request-param.003.json       |   1 -
 .../api/request-param/request-param.004.csv        |   2 -
 .../api/request-param/request-param.005.adm        |   2 -
 .../api/request-param/request-param.006.csv        |   2 -
 .../api/request-param/request-param.007.json       |   1 -
 .../api/request-param/request-param.008.json       |   1 -
 .../async-deferred/async-json/async-json.3.json    |   6 +-
 .../results/json/int01-cleanjson/int01.1.json      |   2 +-
 .../results/json/int01-losslessjson/int01.1.json   |   8 +-
 .../json/issue-ASTERIXDB-1165/nullablefield.1.json |   2 +-
 .../results/numeric/non-finite/non-finite.1.json   |   6 +-
 .../results/parseonly/001/parseonly_01.1.adm       |   2 +-
 .../results/parseonly/001/parseonly_01.2.adm       |   2 +-
 .../results/parseonly/001/parseonly_01.3.adm       |   2 +-
 .../results/parseonly/001/parseonly_01.4.adm       |   2 +-
 .../results/parseonly/001/parseonly_01.5.adm       |   2 +-
 .../apache/asterix/spidersilk/SampleTestIT.java    |  21 +--
 .../apache/hyracks/http/server/utils/HttpUtil.java |   5 +-
 33 files changed, 273 insertions(+), 322 deletions(-)

diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
index 5c47ca2..c83e865 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ExecutionPlansJsonPrintUtil.java
@@ -27,7 +27,7 @@ public class ExecutionPlansJsonPrintUtil {
     private static final String LOGICAL_PLAN_LBL = "logicalPlan";
     private static final String EXPRESSION_TREE_LBL = "expressionTree";
     private static final String REWRITTEN_EXPRESSION_TREE_LBL = "rewrittenExpressionTree";
-    private static final String OPTIMIZED_LOGICAL_PLAN_LBL = "optimizedLogicalPlan";
+    public static final String OPTIMIZED_LOGICAL_PLAN_LBL = "optimizedLogicalPlan";
     private static final String JOB_LBL = "job";
 
     private ExecutionPlansJsonPrintUtil() {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 6e70d27..6cf8454 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -559,12 +559,10 @@ public class QueryServiceRequestParameters {
             return Pair.of(OutputFormat.CSV, Boolean.FALSE);
         } else if (value.equals(HttpUtil.ContentType.JSON)) {
             return Pair.of(OutputFormat.CLEAN_JSON, Boolean.FALSE);
+        } else if (value.equals(HttpUtil.ContentType.ADM)) {
+            return Pair.of(OutputFormat.ADM, Boolean.FALSE);
         } else {
-            Pair<OutputFormat, Boolean> format = fromMime(value);
-            if (format == null) {
-                throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
-            }
-            return format;
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
         }
     }
 
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
index 1624db3..e3e4069 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
@@ -31,6 +31,7 @@ import org.apache.asterix.app.result.fields.MetricsPrinter;
 import org.apache.asterix.common.api.IApplicationContext;
 import org.apache.asterix.common.config.CompilerProperties;
 import org.apache.asterix.test.common.ResultExtractor;
+import org.apache.asterix.testframework.context.TestCaseContext;
 import org.apache.asterix.translator.IStatementExecutor;
 import org.apache.asterix.translator.SessionConfig;
 import org.apache.asterix.translator.SessionOutput;
@@ -77,8 +78,8 @@ public class ResultPrinterTest {
         boolean exceptionThrown = false;
         try {
             // ensure result is valid json and error will be returned and not results.
-            ResultExtractor.extract(IOUtils.toInputStream(resultStr, StandardCharsets.UTF_8), StandardCharsets.UTF_8)
-                    .getResult();
+            ResultExtractor.extract(IOUtils.toInputStream(resultStr, StandardCharsets.UTF_8), StandardCharsets.UTF_8,
+                    TestCaseContext.OutputFormat.CLEAN_JSON).getResult();
         } catch (Exception e) {
             exceptionThrown = true;
             Assert.assertTrue(e.getMessage().contains(expectedException.getMessage()));
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
index 5e53d54..8dab64f 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
@@ -18,6 +18,7 @@
  */
 package org.apache.asterix.test.common;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
@@ -28,14 +29,17 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.testframework.context.TestCaseContext.OutputFormat;
 import org.apache.commons.io.IOUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.PrettyPrinter;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.Iterators;
@@ -47,6 +51,60 @@ import com.google.common.collect.Iterators;
  */
 public class ResultExtractor {
 
+    private static class JsonPrettyPrinter implements PrettyPrinter {
+
+        JsonPrettyPrinter() {
+        }
+
+        @Override
+        public void writeRootValueSeparator(JsonGenerator gen) throws IOException {
+
+        }
+
+        @Override
+        public void writeStartObject(JsonGenerator g) throws IOException {
+            g.writeRaw("{ ");
+        }
+
+        @Override
+        public void writeEndObject(JsonGenerator g, int nrOfEntries) throws IOException {
+            g.writeRaw(" }");
+        }
+
+        @Override
+        public void writeObjectFieldValueSeparator(JsonGenerator jg) throws IOException {
+            jg.writeRaw(": ");
+        }
+
+        @Override
+        public void writeObjectEntrySeparator(JsonGenerator g) throws IOException {
+            g.writeRaw(", ");
+        }
+
+        @Override
+        public void writeStartArray(JsonGenerator g) throws IOException {
+            g.writeRaw("[ ");
+        }
+
+        @Override
+        public void writeEndArray(JsonGenerator g, int nrOfValues) throws IOException {
+            g.writeRaw(" ]");
+        }
+
+        @Override
+        public void writeArrayValueSeparator(JsonGenerator g) throws IOException {
+            g.writeRaw(", ");
+        }
+
+        @Override
+        public void beforeArrayValues(JsonGenerator gen) throws IOException {
+        }
+
+        @Override
+        public void beforeObjectEntries(JsonGenerator gen) throws IOException {
+        }
+    }
+
     private enum ResultField {
         RESULTS("results"),
         REQUEST_ID("requestID"),
@@ -85,11 +143,14 @@ public class ResultExtractor {
 
     private static final Logger LOGGER = LogManager.getLogger();
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final ObjectWriter WRITER = OBJECT_MAPPER.writer();
+    private static final ObjectWriter PP_WRITER = OBJECT_MAPPER.writer(new JsonPrettyPrinter());
+    private static final ObjectReader OBJECT_READER = OBJECT_MAPPER.readerFor(ObjectNode.class);
 
-    public static ExtractedResult extract(InputStream resultStream, Charset resultCharset, String outputFormat)
+    public static ExtractedResult extract(InputStream resultStream, Charset resultCharset, OutputFormat outputFormat)
             throws Exception {
-        return extract(resultStream, EnumSet.of(ResultField.RESULTS, ResultField.WARNINGS), resultCharset,
-                outputFormat);
+        return extract(resultStream, EnumSet.of(ResultField.RESULTS, ResultField.WARNINGS), resultCharset, outputFormat,
+                null);
     }
 
     public static ExtractedResult extract(InputStream resultStream, Charset resultCharset) throws Exception {
@@ -104,13 +165,14 @@ public class ResultExtractor {
         return extract(resultStream, EnumSet.of(ResultField.PROFILE), resultCharset).getResult();
     }
 
-    public static InputStream extractPlans(InputStream resultStream, Charset resultCharset) throws Exception {
-        return extract(resultStream, EnumSet.of(ResultField.PLANS), resultCharset).getResult();
+    public static InputStream extractPlans(InputStream resultStream, Charset resultCharset, String[] plans)
+            throws Exception {
+        return extract(resultStream, EnumSet.of(ResultField.PLANS), resultCharset, OutputFormat.ADM, plans).getResult();
     }
 
     public static String extractHandle(InputStream resultStream, Charset responseCharset) throws Exception {
         String result = IOUtils.toString(resultStream, responseCharset);
-        ObjectNode resultJson = OBJECT_MAPPER.readValue(result, ObjectNode.class);
+        ObjectNode resultJson = OBJECT_READER.readValue(result);
         final JsonNode handle = resultJson.get("handle");
         if (handle != null) {
             return handle.asText();
@@ -126,28 +188,15 @@ public class ResultExtractor {
 
     private static ExtractedResult extract(InputStream resultStream, EnumSet<ResultField> resultFields,
             Charset resultCharset) throws Exception {
-        return extract(resultStream, resultFields, resultCharset, "jsonl"); //default output format type is jsonl
-    }
-
-    private static ExtractedResult extract(InputStream resultStream, EnumSet<ResultField> resultFields,
-            Charset resultCharset, String fmt) throws Exception {
-
-        if (fmt.equals("json")) {
-            return extract(resultStream, resultFields, resultCharset, "[", ",", "]");
-        }
-
-        if (fmt.equals("jsonl")) {
-            return extract(resultStream, resultFields, resultCharset, "", "", "");
-        }
-
-        throw new AsterixException("Unkown output format for result of test query");
+        return extract(resultStream, resultFields, resultCharset, OutputFormat.ADM, null);
     }
 
     private static ExtractedResult extract(InputStream resultStream, EnumSet<ResultField> resultFields,
-            Charset resultCharset, String openMarker, String separator, String closeMarker) throws Exception {
+            Charset resultCharset, OutputFormat fmt, String[] plans) throws Exception {
         ExtractedResult extractedResult = new ExtractedResult();
         final String resultStr = IOUtils.toString(resultStream, resultCharset);
-        final ObjectNode result = OBJECT_MAPPER.readValue(resultStr, ObjectNode.class);
+        final ObjectNode result = OBJECT_READER.readValue(resultStr);
+        final boolean isJsonFormat = isJsonFormat(fmt);
 
         LOGGER.debug("+++++++\n" + result + "\n+++++++\n");
         // if we have errors field in the results, we will always return it
@@ -169,34 +218,31 @@ public class ResultExtractor {
                         if (fieldValue.size() == 0) {
                             resultBuilder.append("");
                         } else if (fieldValue.isArray()) {
-                            if (fieldValue.get(0).isTextual()) {
-                                resultBuilder.append(fieldValue.get(0).asText());
+                            JsonNode oneElement = fieldValue.get(0);
+                            if (oneElement.isTextual()) {
+                                resultBuilder.append(
+                                        isJsonFormat ? PP_WRITER.writeValueAsString(oneElement) : oneElement.asText());
                             } else {
-                                ObjectMapper omm = new ObjectMapper();
-                                omm.enable(SerializationFeature.INDENT_OUTPUT);
-                                resultBuilder
-                                        .append(omm.writer(new DefaultPrettyPrinter()).writeValueAsString(fieldValue));
+                                resultBuilder.append(PP_WRITER.writeValueAsString(oneElement));
                             }
                         } else {
-                            resultBuilder.append(OBJECT_MAPPER.writeValueAsString(fieldValue));
+                            resultBuilder.append(PP_WRITER.writeValueAsString(fieldValue));
                         }
                     } else {
                         JsonNode[] fields = Iterators.toArray(fieldValue.elements(), JsonNode.class);
-                        if (fields.length > 1) {
-                            String sep = openMarker;
+                        if (isJsonFormat) {
                             for (JsonNode f : fields) {
-                                resultBuilder.append(sep);
-                                sep = separator;
-                                if (f.isObject()) {
-
-                                    resultBuilder.append(OBJECT_MAPPER.writeValueAsString(f));
-                                } else {
+                                resultBuilder.append(PP_WRITER.writeValueAsString(f)).append('\n');
+                            }
+                        } else {
+                            for (JsonNode f : fields) {
+                                if (f.isValueNode()) {
                                     resultBuilder.append(f.asText());
+                                } else {
+                                    resultBuilder.append(PP_WRITER.writeValueAsString(f)).append('\n');
                                 }
                             }
-                            resultBuilder.append(closeMarker);
                         }
-
                     }
                     break;
                 case REQUEST_ID:
@@ -207,7 +253,17 @@ public class ResultExtractor {
                 case STATUS:
                 case TYPE:
                 case PLANS:
-                    resultBuilder.append(OBJECT_MAPPER.writeValueAsString(fieldValue));
+                    if (plans == null) {
+                        resultBuilder.append(WRITER.writeValueAsString(fieldValue));
+                    } else {
+                        for (int i = 0, size = plans.length; i < size; i++) {
+                            JsonNode plan = fieldValue.get(plans[i]);
+                            if (plan != null) {
+                                resultBuilder.append(plan.asText());
+                            }
+                        }
+                    }
+
                 case WARNINGS:
                     extractWarnings(fieldValue, extractedResult);
                     break;
@@ -240,4 +296,8 @@ public class ResultExtractor {
         }
         exeResult.setWarnings(warnings);
     }
+
+    private static boolean isJsonFormat(OutputFormat format) {
+        return format == OutputFormat.CLEAN_JSON || format == OutputFormat.LOSSLESS_JSON;
+    }
 }
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 71ef783..7a63685 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -83,6 +83,7 @@ import org.apache.asterix.testframework.xml.ParameterTypeEnum;
 import org.apache.asterix.testframework.xml.TestCase.CompilationUnit;
 import org.apache.asterix.testframework.xml.TestCase.CompilationUnit.Parameter;
 import org.apache.asterix.testframework.xml.TestGroup;
+import org.apache.asterix.translator.ExecutionPlansJsonPrintUtil;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
@@ -114,6 +115,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.util.RawValue;
 
@@ -123,6 +126,13 @@ public class TestExecutor {
      * Static variables
      */
     protected static final Logger LOGGER = LogManager.getLogger();
+    private static final ObjectMapper OM = new ObjectMapper();
+    private static final ObjectWriter OBJECT_WRITER = OM.writer();
+    private static final ObjectReader JSON_NODE_READER = OM.readerFor(JsonNode.class);
+    private static final ObjectReader SINGLE_JSON_NODE_READER = JSON_NODE_READER
+            .with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
+    private static final ObjectReader RESULT_NODE_READER =
+            JSON_NODE_READER.with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
     private static final String AQL = "aql";
     private static final String SQLPP = "sqlpp";
     private static final String DEFAULT_PLAN_FORMAT = "string";
@@ -139,7 +149,7 @@ public class TestExecutor {
     private static final Pattern POLL_DELAY_PATTERN = Pattern.compile("polldelaysecs=(\\d+)(\\D|$)", Pattern.MULTILINE);
     private static final Pattern HANDLE_VARIABLE_PATTERN = Pattern.compile("handlevariable=(\\w+)");
     private static final Pattern RESULT_VARIABLE_PATTERN = Pattern.compile("resultvariable=(\\w+)");
-    private static final Pattern OUTPUTFORMAT_VARIABLE_PATTERN = Pattern.compile("outputformat=(\\w+)");
+    private static final Pattern COMPARE_UNORDERED_ARRAY_PATTERN = Pattern.compile("compareunorderedarray=(\\w+)");
 
     private static final Pattern VARIABLE_REF_PATTERN = Pattern.compile("\\$(\\w+)");
     private static final Pattern HTTP_PARAM_PATTERN =
@@ -236,7 +246,7 @@ public class TestExecutor {
     }
 
     public void runScriptAndCompareWithResult(File scriptFile, File expectedFile, File actualFile,
-            ComparisonEnum compare, Charset actualEncoding) throws Exception {
+            ComparisonEnum compare, Charset actualEncoding, String statement) throws Exception {
         LOGGER.info("Expected results file: {} ", expectedFile);
         boolean regex = false;
         if (expectedFile.getName().endsWith(".ignore")) {
@@ -258,16 +268,8 @@ public class TestExecutor {
                 runScriptAndCompareWithResultRegexAdm(scriptFile, readerExpected, readerActual);
                 return;
             } else if (actualFile.toString().endsWith(".regexjson")) {
-                ObjectMapper OM = new ObjectMapper();
-                JsonNode expectedJson = OM.readTree(readerExpected);
-                JsonNode actualJson = OM.readTree(readerActual);
-                if (expectedJson == null || actualJson == null) {
-                    throw new NullPointerException("Error parsing expected or actual result file for " + scriptFile);
-                }
-                if (!TestHelper.equalJson(expectedJson, actualJson)) {
-                    throw new ComparisonException("Result for " + scriptFile + " didn't match the expected JSON"
-                            + "\nexpected result:\n" + expectedJson + "\nactual result:\n" + actualJson);
-                }
+                boolean compareUnorderedArray = statement != null && getCompareUnorderedArray(statement);
+                runScriptAndCompareWithResultRegexJson(scriptFile, readerExpected, readerActual, compareUnorderedArray);
                 return;
             }
             String lineExpected, lineActual;
@@ -501,6 +503,30 @@ public class TestExecutor {
         }
     }
 
+    private static void runScriptAndCompareWithResultRegexJson(File scriptFile, BufferedReader readerExpected,
+            BufferedReader readerActual, boolean compareUnorderedArray) throws ComparisonException, IOException {
+        JsonNode expectedJson, actualJson;
+        try {
+            expectedJson = SINGLE_JSON_NODE_READER.readTree(readerExpected);
+        } catch (JsonProcessingException e) {
+            throw new ComparisonException("Invalid expected JSON for: " + scriptFile);
+        }
+        try {
+            actualJson = SINGLE_JSON_NODE_READER.readTree(readerActual);
+        } catch (JsonProcessingException e) {
+            throw new ComparisonException("Invalid actual JSON for: " + scriptFile);
+        }
+        if (expectedJson == null) {
+            throw new ComparisonException("No expected result for: " + scriptFile);
+        } else if (actualJson == null) {
+            throw new ComparisonException("No actual result for: " + scriptFile);
+        }
+        if (!TestHelper.equalJson(expectedJson, actualJson, compareUnorderedArray)) {
+            throw new ComparisonException("Result for " + scriptFile + " didn't match the expected JSON"
+                    + "\nexpected result:\n" + expectedJson + "\nactual result:\n" + actualJson);
+        }
+    }
+
     // For tests where you simply want the byte-for-byte output.
     private static void writeOutputToFile(File actualFile, InputStream resultStream) throws Exception {
         final File parentDir = actualFile.getParentFile();
@@ -559,8 +585,7 @@ public class TestExecutor {
             String[] errors;
             try {
                 // First try to parse the response for a JSON error response.
-                ObjectMapper om = new ObjectMapper();
-                JsonNode result = om.readTree(errorBody);
+                JsonNode result = JSON_NODE_READER.readTree(errorBody);
                 errors = new String[] { result.get("error-code").get(1).asText(), result.get("summary").asText(),
                         result.get("stacktrace").asText() };
             } catch (Exception e) {
@@ -626,8 +651,9 @@ public class TestExecutor {
     }
 
     public List<Parameter> constructQueryParameters(String str, OutputFormat fmt, List<Parameter> params) {
-        List<Parameter> newParams = upsertParam(params, QueryServiceRequestParameters.Parameter.FORMAT.str(),
-                ParameterTypeEnum.STRING, fmt.mimeType());
+        List<Parameter> newParams = setFormatInAccept(fmt) ? params
+                : upsertParam(params, QueryServiceRequestParameters.Parameter.FORMAT.str(), ParameterTypeEnum.STRING,
+                        fmt.extension());
 
         newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.PLAN_FORMAT.str(),
                 ParameterTypeEnum.STRING, DEFAULT_PLAN_FORMAT);
@@ -652,7 +678,7 @@ public class TestExecutor {
                 : constructPostMethodUrl(str, uri, "statement", params);
         // Set accepted output response type
         method.setHeader("Origin", uri.getScheme() + uri.getAuthority());
-        method.setHeader("Accept", OutputFormat.CLEAN_JSON.mimeType());
+        method.setHeader("Accept", setFormatInAccept(fmt) ? fmt.mimeType() : OutputFormat.CLEAN_JSON.mimeType());
         method.setHeader("Accept-Charset", responseCharset.name());
         if (!responseCharset.equals(UTF_8)) {
             LOGGER.info("using Accept-Charset: {}", responseCharset.name());
@@ -672,6 +698,10 @@ public class TestExecutor {
                 responseCharset, responseCodeValidator, cancellable);
     }
 
+    private static boolean setFormatInAccept(OutputFormat fmt) {
+        return fmt == OutputFormat.LOSSLESS_JSON || fmt == OutputFormat.CSV_HEADER;
+    }
+
     public void setAvailableCharsets(Charset... charsets) {
         setAvailableCharsets(Arrays.asList(charsets));
     }
@@ -802,8 +832,7 @@ public class TestExecutor {
             List<Parameter> otherParams) {
         Objects.requireNonNull(stmtParam, "statement parameter required");
         RequestBuilder builder = RequestBuilder.post(uri);
-        ObjectMapper om = new ObjectMapper();
-        ObjectNode content = om.createObjectNode();
+        ObjectNode content = OM.createObjectNode();
         for (Parameter param : upsertParam(otherParams, stmtParam, ParameterTypeEnum.STRING, statement)) {
             String paramName = param.getName();
             ParameterTypeEnum paramType = param.getType();
@@ -823,7 +852,7 @@ public class TestExecutor {
             }
         }
         try {
-            builder.setEntity(new StringEntity(om.writeValueAsString(content),
+            builder.setEntity(new StringEntity(OBJECT_WRITER.writeValueAsString(content),
                     ContentType.create(ContentType.APPLICATION_JSON.getMimeType(),
                             statement.length() > MAX_NON_UTF_8_STATEMENT_SIZE ? UTF_8 : nextCharset())));
         } catch (JsonProcessingException e) {
@@ -1034,7 +1063,7 @@ public class TestExecutor {
                         + "_qar.adm");
                 writeOutputToFile(qarFile, resultStream);
                 qbcFile = getTestCaseQueryBeforeCrashFile(actualPath, testCaseCtx, cUnit);
-                runScriptAndCompareWithResult(testFile, qbcFile, qarFile, ComparisonEnum.TEXT, UTF_8);
+                runScriptAndCompareWithResult(testFile, qbcFile, qarFile, ComparisonEnum.TEXT, UTF_8, statement);
                 break;
             case "txneu": // eu represents erroneous update
                 try {
@@ -1301,7 +1330,8 @@ public class TestExecutor {
                 }
             } else {
                 writeOutputToFile(actualResultFile, resultStream);
-                runScriptAndCompareWithResult(testFile, expectedResultFile, actualResultFile, compare, UTF_8);
+                runScriptAndCompareWithResult(testFile, expectedResultFile, actualResultFile, compare, UTF_8,
+                        statement);
             }
         }
         queryCount.increment();
@@ -1341,16 +1371,11 @@ public class TestExecutor {
                     resultStream = ResultExtractor.extractProfile(resultStream, responseCharset);
                     break;
                 case PLANS_QUERY_TYPE:
-                    resultStream = ResultExtractor.extractPlans(resultStream, responseCharset);
+                    String[] plans = plans(statement);
+                    resultStream = ResultExtractor.extractPlans(resultStream, responseCharset, plans);
                     break;
                 default:
-                    String outputFormatVariable = getOutputFormatVariable(statement);
-                    if ((outputFormatVariable == null) || (outputFormatVariable.equals("jsonl"))) {
-                        extractedResult = ResultExtractor.extract(resultStream, responseCharset);
-                    } else {
-                        extractedResult = ResultExtractor.extract(resultStream, responseCharset, "json");
-                    }
-
+                    extractedResult = ResultExtractor.extract(resultStream, responseCharset, fmt);
                     resultStream = extractedResult.getResult();
                     break;
             }
@@ -1385,7 +1410,8 @@ public class TestExecutor {
                         + ", filectxs.size: " + numResultFiles);
             }
         }
-        runScriptAndCompareWithResult(testFile, expectedResultFile, actualResultFile, compare, responseCharset);
+        runScriptAndCompareWithResult(testFile, expectedResultFile, actualResultFile, compare, responseCharset,
+                statement);
         if (!reqType.equals("validate")) {
             queryCount.increment();
         }
@@ -1557,7 +1583,7 @@ public class TestExecutor {
     private InputStream executeUpdateOrDdl(String statement, OutputFormat outputFormat, URI serviceUri)
             throws Exception {
         InputStream resultStream = executeQueryService(statement, serviceUri, outputFormat, UTF_8);
-        return ResultExtractor.extract(resultStream, UTF_8).getResult();
+        return ResultExtractor.extract(resultStream, UTF_8, outputFormat).getResult();
     }
 
     protected static boolean isExpected(Exception e, CompilationUnit cUnit) {
@@ -1609,9 +1635,9 @@ public class TestExecutor {
         return resultVariableMatcher.find() ? resultVariableMatcher.group(1) : null;
     }
 
-    protected static String getOutputFormatVariable(String statement) {
-        final Matcher outputFormatVariableMatcher = OUTPUTFORMAT_VARIABLE_PATTERN.matcher(statement);
-        return outputFormatVariableMatcher.find() ? outputFormatVariableMatcher.group(1) : null;
+    protected static boolean getCompareUnorderedArray(String statement) {
+        final Matcher matcher = COMPARE_UNORDERED_ARRAY_PATTERN.matcher(statement);
+        return matcher.find() && Boolean.parseBoolean(matcher.group(1));
     }
 
     protected static String replaceVarRef(String statement, Map<String, Object> variableCtx) {
@@ -1743,7 +1769,7 @@ public class TestExecutor {
         StringWriter actual = new StringWriter();
         IOUtils.copy(executeJSONGet, actual, UTF_8);
         String config = actual.toString();
-        int nodePid = new ObjectMapper().readValue(config, ObjectNode.class).get("pid").asInt();
+        int nodePid = JSON_NODE_READER.<ObjectNode> readValue(config).get("pid").asInt();
         if (nodePid <= 1) {
             throw new IllegalArgumentException("Could not retrieve node pid from admin API");
         }
@@ -1773,8 +1799,7 @@ public class TestExecutor {
         StringWriter actual = new StringWriter();
         IOUtils.copy(executeJSONGet, actual, UTF_8);
         String config = actual.toString();
-        ObjectMapper om = new ObjectMapper();
-        String logDir = om.readTree(config).findPath("txn.log.dir").asText();
+        String logDir = JSON_NODE_READER.readTree(config).findPath("txn.log.dir").asText();
         FileUtils.deleteQuietly(new File(logDir));
     }
 
@@ -1997,7 +2022,7 @@ public class TestExecutor {
                     dropStatement.append(";\n");
                     resultStream = executeQueryService(dropStatement.toString(), getEndpoint(Servlets.QUERY_SERVICE),
                             OutputFormat.CLEAN_JSON, UTF_8);
-                    ResultExtractor.extract(resultStream, UTF_8);
+                    ResultExtractor.extract(resultStream, UTF_8, OutputFormat.CLEAN_JSON);
                 }
             }
         } catch (Throwable th) {
@@ -2007,17 +2032,15 @@ public class TestExecutor {
     }
 
     private JsonNode extractResult(String jsonString) throws IOException {
-        ObjectMapper om = new ObjectMapper();
-        om.setConfig(om.getDeserializationConfig().with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT));
         try {
-            final JsonNode result = om.readValue(jsonString, ObjectNode.class).get("results");
+            final JsonNode result = RESULT_NODE_READER.<ObjectNode> readValue(jsonString).get("results");
             if (result == null) {
                 throw new IllegalArgumentException("No field 'results' in " + jsonString);
             }
             return result;
         } catch (JsonMappingException e) {
             LOGGER.warn("error mapping response '{}' to json", jsonString, e);
-            return om.createArrayNode();
+            return OM.createArrayNode();
         }
     }
 
@@ -2044,8 +2067,7 @@ public class TestExecutor {
                     if (statusCode != HttpStatus.SC_OK) {
                         throw new Exception("HTTP error " + statusCode + ":\n" + response);
                     }
-                    ObjectMapper om = new ObjectMapper();
-                    ObjectNode result = (ObjectNode) om.readTree(response);
+                    ObjectNode result = (ObjectNode) JSON_NODE_READER.readTree(response);
                     if (result.get("state").asText().matches(desiredState)) {
                         break;
                     }
@@ -2184,6 +2206,19 @@ public class TestExecutor {
         }
     }
 
+    private static String[] plans(String statement) {
+        boolean requestingLogicalPlan = isRequestingLogicalPlan(statement);
+        return requestingLogicalPlan ? new String[] { ExecutionPlansJsonPrintUtil.OPTIMIZED_LOGICAL_PLAN_LBL } : null;
+    }
+
+    private static boolean isRequestingLogicalPlan(String statement) {
+        List<Parameter> httpParams = extractParameters(statement);
+        return httpParams.stream()
+                .anyMatch(param -> param.getName()
+                        .equals(QueryServiceRequestParameters.Parameter.OPTIMIZED_LOGICAL_PLAN.str())
+                        && param.getValue().equals("true"));
+    }
+
     protected static boolean containsClientContextID(String statement) {
         List<Parameter> httpParams = extractParameters(statement);
         return httpParams.stream().map(Parameter::getName)
@@ -2197,9 +2232,10 @@ public class TestExecutor {
     private InputStream query(CompilationUnit cUnit, String testFile, String statement, Charset responseCharset)
             throws Exception {
         final URI uri = getQueryServiceUri(testFile);
-        final InputStream inputStream = executeQueryService(statement, OutputFormat.forCompilationUnit(cUnit), uri,
-                cUnit.getParameter(), true, responseCharset);
-        return ResultExtractor.extract(inputStream, responseCharset).getResult();
+        OutputFormat outputFormat = OutputFormat.forCompilationUnit(cUnit);
+        final InputStream inputStream =
+                executeQueryService(statement, outputFormat, uri, cUnit.getParameter(), true, responseCharset);
+        return ResultExtractor.extract(inputStream, responseCharset, outputFormat).getResult();
     }
 
     private URI getQueryServiceUri(String extension) throws URISyntaxException {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
index 619ce8c..137efdb 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
@@ -141,7 +141,7 @@ public final class TestHelper {
         return RequestParameters.deserializeParameterValues(RequestParameters.serializeParameterValues(stmtParams));
     }
 
-    public static boolean equalJson(JsonNode expectedJson, JsonNode actualJson) {
+    public static boolean equalJson(JsonNode expectedJson, JsonNode actualJson, boolean compareUnorderedArray) {
         if (expectedJson == actualJson) {
             return true;
         }
@@ -149,8 +149,17 @@ public final class TestHelper {
         if (expectedJson == null || actualJson == null) {
             return false;
         }
+        if ((expectedJson.isMissingNode() && !actualJson.isMissingNode())
+                || (!expectedJson.isMissingNode() && actualJson.isMissingNode())) {
+            return false;
+        }
         // both are not null
-        if (!isRegexField(expectedJson) && expectedJson.getNodeType() != actualJson.getNodeType()) {
+        if (isRegexField(expectedJson)) {
+            String expectedRegex = expectedJson.asText();
+            String actualAsString = actualJson.isValueNode() ? actualJson.asText() : actualJson.toString();
+            expectedRegex = expectedRegex.substring(2, expectedRegex.length() - 1);
+            return actualAsString.matches(expectedRegex);
+        } else if (expectedJson.getNodeType() != actualJson.getNodeType()) {
             return false;
         } else if (expectedJson.isArray() && actualJson.isArray()) {
             ArrayNode expectedArray = (ArrayNode) expectedJson;
@@ -158,22 +167,8 @@ public final class TestHelper {
             if (expectedArray.size() != actualArray.size()) {
                 return false;
             }
-            boolean found;
-            BitSet alreadyMatched = new BitSet(actualArray.size());
-            for (int i = 0; i < expectedArray.size(); i++) {
-                found = false;
-                for (int k = 0; k < actualArray.size(); k++) {
-                    if (!alreadyMatched.get(k) && equalJson(expectedArray.get(i), actualArray.get(k))) {
-                        alreadyMatched.set(k);
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    return false;
-                }
-            }
-            return true;
+            return compareUnorderedArray ? compareUnordered(expectedArray, actualArray)
+                    : compareOrdered(expectedArray, actualArray);
         } else if (expectedJson.isObject() && actualJson.isObject()) {
             // assumes no duplicates in field names
             ObjectNode expectedObject = (ObjectNode) expectedJson;
@@ -187,22 +182,47 @@ public final class TestHelper {
             while (expectedFields.hasNext()) {
                 expectedField = expectedFields.next();
                 actualFieldValue = actualObject.get(expectedField.getKey());
-                if (actualFieldValue == null || !equalJson(expectedField.getValue(), actualFieldValue)) {
+                if (actualFieldValue == null
+                        || !equalJson(expectedField.getValue(), actualFieldValue, compareUnorderedArray)) {
                     return false;
                 }
             }
             return true;
         }
         // value node
-        String expectedAsString = expectedJson.asText();
-        String actualAsString = actualJson.asText();
-        if (expectedAsString.startsWith("R{")) {
-            expectedAsString = expectedAsString.substring(2, expectedAsString.length() - 1);
-            return actualAsString.matches(expectedAsString);
-        }
+        String expectedAsString = expectedJson.isValueNode() ? expectedJson.asText() : expectedJson.toString();
+        String actualAsString = actualJson.isValueNode() ? actualJson.asText() : actualJson.toString();
         return expectedAsString.equals(actualAsString);
     }
 
+    private static boolean compareUnordered(ArrayNode expectedArray, ArrayNode actualArray) {
+        BitSet alreadyMatched = new BitSet(actualArray.size());
+        for (int i = 0; i < expectedArray.size(); i++) {
+            boolean found = false;
+            JsonNode expectedElement = expectedArray.get(i);
+            for (int k = 0; k < actualArray.size(); k++) {
+                if (!alreadyMatched.get(k) && equalJson(expectedElement, actualArray.get(k), true)) {
+                    alreadyMatched.set(k);
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean compareOrdered(ArrayNode expectedArray, ArrayNode actualArray) {
+        for (int i = 0, size = expectedArray.size(); i < size; i++) {
+            if (!equalJson(expectedArray.get(i), actualArray.get(i), false)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private static boolean isRegexField(JsonNode expectedJson) {
         if (expectedJson.isTextual()) {
             String regexValue = expectedJson.asText();
@@ -218,16 +238,4 @@ public final class TestHelper {
         objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
         return objectMapper;
     }
-
-    public static void main(String[] args) throws Exception {
-        ObjectMapper om = createObjectMapper();
-        String patternFile = args[0];
-        String instanceFile = args[1];
-        if (equalJson(om.readTree(new File(patternFile)), om.readTree(new File(instanceFile)))) {
-            System.out.println(instanceFile + " matches " + patternFile);
-        } else {
-            System.out.println(instanceFile + " does not match " + patternFile);
-            System.exit(1);
-        }
-    }
 }
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
index 611d5ea..970cbc0 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
@@ -163,7 +163,7 @@ public class ParserTestExecutor extends TestExecutor {
             writer.close();
             // Compares the actual result and the expected result.
             runScriptAndCompareWithResult(queryFile, expectedFile, actualResultFile, ComparisonEnum.TEXT,
-                    StandardCharsets.UTF_8);
+                    StandardCharsets.UTF_8, null);
         } catch (Exception e) {
             GlobalConfig.ASTERIX_LOGGER.warn("Failed while testing file " + queryFile);
             throw e;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
deleted file mode 100644
index ba37336..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=application/json
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
deleted file mode 100644
index b5d0d64..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=text/csv
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
deleted file mode 100644
index 9d3b964..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=application/x-adm
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
deleted file mode 100644
index d667f48..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=text/csv;header=absent
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
deleted file mode 100644
index cba7638..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=application/json;lossless=true
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
deleted file mode 100644
index 7b6c450..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// requesttype=application/json
-// param format:string=application/json;lossless=false
-
-from [1, 2] as v
-select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan/full-scan.3.profile.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan/full-scan.3.profile.sqlpp
index 9db1d12..606a2c2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan/full-scan.3.profile.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan/full-scan.3.profile.sqlpp
@@ -21,7 +21,7 @@
  * Expected Res : Success
  * Date         : 28 Sep 2017
  */
-
+-- compareunorderedarray=true
 use test;
 
 select count(*) from Customers;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
index 83ce118..cb88308 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
@@ -1 +1,2 @@
-{"v":1}{"v":2}
\ No newline at end of file
+{ "v": 1 }
+{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
deleted file mode 100644
index 83ce118..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
deleted file mode 100644
index 7a754f4..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-1
-2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
deleted file mode 100644
index cb88308..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
+++ /dev/null
@@ -1,2 +0,0 @@
-{ "v": 1 }
-{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
deleted file mode 100644
index 7a754f4..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-1
-2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
deleted file mode 100644
index 32c4637..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":{"int64":1}}{"v":{"int64":2}}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
deleted file mode 100644
index 83ce118..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/async-deferred/async-json/async-json.3.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/async-deferred/async-json/async-json.3.json
index d4e1a2d..2b249bc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/async-deferred/async-json/async-json.3.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/async-deferred/async-json/async-json.3.json
@@ -1 +1,5 @@
-{"i":1,"i2":1}{"i":2,"i2":4}{"i":3,"i2":9}{"i":4,"i2":16}{"i":5,"i2":25}
\ No newline at end of file
+{ "i": 1, "i2": 1 }
+{ "i": 2, "i2": 4 }
+{ "i": 3, "i2": 9 }
+{ "i": 4, "i2": 16 }
+{ "i": 5, "i2": 25 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-cleanjson/int01.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-cleanjson/int01.1.json
index f83d375..1684a9d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-cleanjson/int01.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-cleanjson/int01.1.json
@@ -1 +1 @@
-[ [ 1, 2 ] ]
\ No newline at end of file
+[ 1, 2 ]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-losslessjson/int01.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-losslessjson/int01.1.json
index 2280279..ffd7602 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-losslessjson/int01.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/int01-losslessjson/int01.1.json
@@ -1,7 +1 @@
-[ {
-  "orderedlist" : [ {
-    "int64" : 1
-  }, {
-    "int64" : 2
-  } ]
-} ]
+{ "orderedlist": [ { "int64": 1 }, { "int64": 2 } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/issue-ASTERIXDB-1165/nullablefield.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/issue-ASTERIXDB-1165/nullablefield.1.json
index 6f98a7f..e440e5c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/json/issue-ASTERIXDB-1165/nullablefield.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/json/issue-ASTERIXDB-1165/nullablefield.1.json
@@ -1 +1 @@
-[ 3 ]
+3
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/non-finite/non-finite.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/non-finite/non-finite.1.json
index d576906..4654e4e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/non-finite/non-finite.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/non-finite/non-finite.1.json
@@ -1,5 +1 @@
-[ {
-  "NaN" : "NaN",
-  "Infinity" : "INF",
-  "-Infinity" : "-INF"
-} ]
+{ "NaN": "NaN", "Infinity": "INF", "-Infinity": "-INF" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.1.adm
index 70522ea..f21a0e3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.1.adm
@@ -1 +1 @@
-{"statement-parameters":["qname"]}
+{ "statement-parameters": [ "qname" ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.2.adm
index 3f0a194..6edda2a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.2.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.2.adm
@@ -1 +1 @@
-{"statement-parameters":["p_arr","p_bool","p_dbl","p_dec","p_int","p_null","p_obj","p_str"]}
+{ "statement-parameters": [ "p_arr", "p_bool", "p_dbl", "p_dec", "p_int", "p_null", "p_obj", "p_str" ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.3.adm
index d2b0d34..9099900 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.3.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.3.adm
@@ -1 +1 @@
-{"statement-parameters":[1,"qname","val"]}
+{ "statement-parameters": [ 1, "qname", "val" ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.4.adm
index 782b0af..211bccf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.4.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.4.adm
@@ -1 +1 @@
-{"statement-parameters":["p_int","p_str"]}
+{ "statement-parameters": [ "p_int", "p_str" ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.5.adm
index c7715a1..acd0477 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.5.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/parseonly/001/parseonly_01.5.adm
@@ -1 +1 @@
-{"statement-parameters":[1,2,"p_int","p_str"]}
+{ "statement-parameters": [ 1, 2, "p_int", "p_str" ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-spidersilk/src/test/java/org/apache/asterix/spidersilk/SampleTestIT.java b/asterixdb/asterix-spidersilk/src/test/java/org/apache/asterix/spidersilk/SampleTestIT.java
index b3b73bf..07c0fc6 100644
--- a/asterixdb/asterix-spidersilk/src/test/java/org/apache/asterix/spidersilk/SampleTestIT.java
+++ b/asterixdb/asterix-spidersilk/src/test/java/org/apache/asterix/spidersilk/SampleTestIT.java
@@ -19,8 +19,6 @@
 package org.apache.asterix.spidersilk;
 
 import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
 
 import org.apache.asterix.test.common.TestExecutor;
 import org.apache.asterix.testframework.context.TestCaseContext;
@@ -31,7 +29,10 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.MappingIterator;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
 
 import me.arminb.spidersilk.SpiderSilkRunner;
 import me.arminb.spidersilk.dsl.entities.Deployment;
@@ -76,12 +77,16 @@ public class SampleTestIT {
         InputStream resultStream = testExecutor.executeSqlppUpdateOrDdl(query, TestCaseContext.OutputFormat.CLEAN_JSON);
 
         ObjectMapper objectMapper = new ObjectMapper();
-        List<Map<String, String>> result = objectMapper.readValue(resultStream, List.class);
-
-        Assert.assertEquals(1, result.size());
-        Assert.assertEquals(123, result.get(0).get("id"));
-        Assert.assertEquals("John Doe", result.get(0).get("name"));
-
+        ObjectReader objectReader = objectMapper.readerFor(JsonNode.class);
+        MappingIterator<JsonNode> jsonIterator = objectReader.readValues(resultStream);
+        int size = 0;
+        while (jsonIterator.hasNext()) {
+            size++;
+            JsonNode result = jsonIterator.next();
+            Assert.assertEquals(1, size);
+            Assert.assertEquals(123, result.get("id").asInt());
+            Assert.assertEquals("John Doe", result.get("name").asText());
+        }
         logger.info("The fetched record matches the inserted record");
     }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
index 591cf8c..8403dce 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
@@ -65,11 +65,12 @@ public class HttpUtil {
     }
 
     public static class ContentType {
+        public static final String ADM = "adm";
+        public static final String JSON = "json";
+        public static final String CSV = "csv";
         public static final String APPLICATION_ADM = "application/x-adm";
         public static final String APPLICATION_JSON = "application/json";
-        public static final String JSON = "json";
         public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
-        public static final String CSV = "csv";
         public static final String TEXT_CSV = "text/csv";
         public static final String IMG_PNG = "image/png";
         public static final String TEXT_HTML = "text/html";