aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/json
diff options
context:
space:
mode:
authorGravatar Nicolas Noble <nnoble@google.com>2015-01-27 19:12:26 -0800
committerGravatar Nicolas Noble <nnoble@google.com>2015-01-27 19:12:26 -0800
commit66b5bba25bbfa5b13f527846ee35e18334e5e4ed (patch)
tree26dfa8551fc3715abb2da3111832d10af72d5630 /test/core/json
parent8c2be9bbff075ea8090dcf1332a1d94e21126524 (diff)
Fixing a couple of minor bugs, and adding a few tests.
Diffstat (limited to 'test/core/json')
-rw-r--r--test/core/json/json_rewrite.c261
-rw-r--r--test/core/json/json_test.c124
-rw-r--r--test/core/json/rewrite_test_input.json203
-rw-r--r--test/core/json/rewrite_test_output_condensed.json1
-rw-r--r--test/core/json/rewrite_test_output_indented.json272
5 files changed, 861 insertions, 0 deletions
diff --git a/test/core/json/json_rewrite.c b/test/core/json/json_rewrite.c
new file mode 100644
index 0000000000..f29f124e30
--- /dev/null
+++ b/test/core/json/json_rewrite.c
@@ -0,0 +1,261 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <grpc/support/cmdline.h>
+#include <grpc/support/alloc.h>
+
+#include "src/core/json/json_reader.h"
+#include "src/core/json/json_writer.h"
+
+typedef struct json_writer_userdata {
+ FILE* out;
+} json_writer_userdata;
+
+typedef struct stacked_container {
+ grpc_json_type type;
+ struct stacked_container* next;
+} stacked_container;
+
+typedef struct json_reader_userdata {
+ FILE* in;
+ grpc_json_writer* writer;
+ char* scratchpad;
+ char* ptr;
+ size_t free_space;
+ size_t allocated;
+ size_t string_len;
+ stacked_container* top;
+} json_reader_userdata;
+
+static void json_writer_output_char(void* userdata, char c) {
+ json_writer_userdata* state = userdata;
+ fputc(c, state->out);
+}
+
+static void json_writer_output_string(void* userdata, const char* str) {
+ json_writer_userdata* state = userdata;
+ fputs(str, state->out);
+}
+
+static void json_writer_output_string_with_len(void* userdata, const char* str,
+ size_t len) {
+ json_writer_userdata* state = userdata;
+ fwrite(str, len, 1, state->out);
+}
+
+grpc_json_writer_vtable writer_vtable = {
+ json_writer_output_char,
+ json_writer_output_string,
+ json_writer_output_string_with_len
+};
+
+static void check_string(json_reader_userdata* state, size_t needed) {
+ if (state->free_space >= needed) return;
+ needed -= state->free_space;
+ needed = (needed + 0xff) & ~0xff;
+ state->scratchpad = gpr_realloc(state->scratchpad, state->allocated + needed);
+ state->free_space += needed;
+ state->allocated += needed;
+}
+
+static void json_reader_string_clear(void* userdata) {
+ json_reader_userdata* state = userdata;
+ state->free_space = state->allocated;
+ state->string_len = 0;
+}
+
+static void json_reader_string_add_char(void* userdata, gpr_uint32 c) {
+ json_reader_userdata* state = userdata;
+ check_string(state, 1);
+ state->scratchpad[state->string_len++] = c;
+}
+
+static void json_reader_string_add_utf32(void* userdata, gpr_uint32 c) {
+ if (c <= 0x7f) {
+ json_reader_string_add_char(userdata, c);
+ } else if (c <= 0x7ff) {
+ int b1 = 0xc0 | ((c >> 6) & 0x1f);
+ int b2 = 0x80 | (c & 0x3f);
+ json_reader_string_add_char(userdata, b1);
+ json_reader_string_add_char(userdata, b2);
+ } else if (c <= 0xffff) {
+ int b1 = 0xe0 | ((c >> 12) & 0x0f);
+ int b2 = 0x80 | ((c >> 6) & 0x3f);
+ int b3 = 0x80 | (c & 0x3f);
+ json_reader_string_add_char(userdata, b1);
+ json_reader_string_add_char(userdata, b2);
+ json_reader_string_add_char(userdata, b3);
+ } else if (c <= 0x1fffff) {
+ int b1 = 0xf0 | ((c >> 18) & 0x07);
+ int b2 = 0x80 | ((c >> 12) & 0x3f);
+ int b3 = 0x80 | ((c >> 6) & 0x3f);
+ int b4 = 0x80 | (c & 0x3f);
+ json_reader_string_add_char(userdata, b1);
+ json_reader_string_add_char(userdata, b2);
+ json_reader_string_add_char(userdata, b3);
+ json_reader_string_add_char(userdata, b4);
+ }
+}
+
+static gpr_uint32 json_reader_read_char(void* userdata) {
+ gpr_uint32 r;
+ json_reader_userdata* state = userdata;
+
+ r = fgetc(state->in);
+ if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF;
+ return r;
+}
+
+static void json_reader_container_begins(void* userdata, grpc_json_type type) {
+ json_reader_userdata* state = userdata;
+ stacked_container* container = gpr_malloc(sizeof(stacked_container));
+
+ container->type = type;
+ container->next = state->top;
+ state->top = container;
+
+ grpc_json_writer_container_begins(state->writer, type);
+}
+
+static grpc_json_type json_reader_container_ends(void* userdata) {
+ json_reader_userdata* state = userdata;
+ stacked_container* container = state->top;
+
+ grpc_json_writer_container_ends(state->writer, container->type);
+ state->top = container->next;
+ gpr_free(container);
+ return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL;
+}
+
+static void json_reader_set_key(void* userdata) {
+ json_reader_userdata* state = userdata;
+ json_reader_string_add_char(userdata, 0);
+
+ grpc_json_writer_object_key(state->writer, state->scratchpad);
+}
+
+static void json_reader_set_string(void* userdata) {
+ json_reader_userdata* state = userdata;
+ json_reader_string_add_char(userdata, 0);
+
+ grpc_json_writer_value_string(state->writer, state->scratchpad);
+}
+
+static int json_reader_set_number(void* userdata) {
+ json_reader_userdata* state = userdata;
+
+ grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad,
+ state->string_len - 1);
+
+ return 1;
+}
+
+static void json_reader_set_true(void* userdata) {
+ json_reader_userdata* state = userdata;
+
+ grpc_json_writer_value_raw_with_len(state->writer, "true", 4);
+}
+
+static void json_reader_set_false(void* userdata) {
+ json_reader_userdata* state = userdata;
+
+ grpc_json_writer_value_raw_with_len(state->writer, "false", 5);
+}
+
+static void json_reader_set_null(void* userdata) {
+ json_reader_userdata* state = userdata;
+
+ grpc_json_writer_value_raw_with_len(state->writer, "null", 4);
+}
+
+static grpc_json_reader_vtable reader_vtable = {
+ json_reader_string_clear,
+ json_reader_string_add_char,
+ json_reader_string_add_utf32,
+ json_reader_read_char,
+ json_reader_container_begins,
+ json_reader_container_ends,
+ json_reader_set_key,
+ json_reader_set_string,
+ json_reader_set_number,
+ json_reader_set_true,
+ json_reader_set_false,
+ json_reader_set_null
+};
+
+int rewrite(FILE* in, FILE* out, int indent) {
+ grpc_json_writer writer;
+ grpc_json_reader reader;
+ grpc_json_reader_status status;
+ json_writer_userdata writer_user;
+ json_reader_userdata reader_user;
+
+ reader_user.writer = &writer;
+ reader_user.in = in;
+ reader_user.top = NULL;
+ reader_user.scratchpad = NULL;
+ reader_user.string_len = 0;
+ reader_user.free_space = 0;
+ reader_user.allocated = 0;
+
+ writer_user.out = out;
+
+ grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user);
+ grpc_json_reader_init(&reader, &reader_vtable, &reader_user);
+
+ status = grpc_json_reader_run(&reader);
+
+ free(reader_user.scratchpad);
+ while (reader_user.top) {
+ stacked_container* container = reader_user.top;
+ reader_user.top = container->next;
+ free(container);
+ }
+
+ return status == GRPC_JSON_DONE;
+}
+
+int main(int argc, char** argv) {
+ int indent = 2;
+ gpr_cmdline* cl;
+
+ cl = gpr_cmdline_create(NULL);
+ gpr_cmdline_add_int(cl, "indent", NULL, &indent);
+ gpr_cmdline_parse(cl, argc, argv);
+ gpr_cmdline_destroy(cl);
+
+ return rewrite(stdin, stdout, indent) ? 0 : 1;
+}
diff --git a/test/core/json/json_test.c b/test/core/json/json_test.c
new file mode 100644
index 0000000000..582ad181aa
--- /dev/null
+++ b/test/core/json/json_test.c
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/useful.h>
+#include <grpc/support/log.h>
+#include "src/core/json/json.h"
+#include "src/core/support/string.h"
+
+#include "test/core/util/test_config.h"
+
+typedef struct testing_pair {
+ const char* input;
+ const char* output;
+} testing_pair;
+
+static testing_pair testing_pairs[] = {
+ { " \"a\" ", "\"a\"" },
+ { "\"\\u0020\\\\\\u0010\\u000a\\u000D\"", "\" \\\\\\u0010\\n\\r\"" },
+ { "\"๐„ž\"", "\"\\ud834\\udd1e\"" },
+ { "\"\\ud834\\udd1e\"", "\"\\ud834\\udd1e\"" },
+ { "\"\xf0\x9d\x84\x9e\"", "\"\\ud834\\udd1e\"" },
+ { " [ [ ] , { } , [ ] ] ", "[[],{},[]]", },
+ { " { \"\\na , b\": [] } ", "{\"\\na , b\":[]}" },
+ { "\"abc\xf0\x9d\x24\"", "\"abc\"" },
+ { "[0, 42 , 0.0123, 123.456]", "[0,42,0.0123,123.456]"},
+ { "[1e4,-53.235e-31, 0.3e+3]", "[1e4,-53.235e-31,0.3e+3]" },
+ { "[true, false, null]", "[true,false,null]" },
+ { "\\", NULL },
+ { "\"\\x", NULL },
+ { "\"\\u123x", NULL },
+ { "\"\\ud834f", NULL },
+ { "\"\\udd1ef", NULL },
+ { "\"\\ud834\\ud834\"", NULL },
+ { "\"\\ud834\\u1234\"", NULL },
+ { "\"\n\"", NULL },
+ { "", NULL },
+ { "{},", NULL },
+ { "{}}", NULL },
+ { "[]]", NULL },
+ { "{,}", NULL },
+ { "[1,2,3,4,]", NULL },
+ { "[\"x\":0]", NULL },
+ { "1.", NULL },
+ { "1e", NULL },
+ { ".12", NULL },
+ { "1.x", NULL },
+ { "1.12x", NULL },
+ { "1ex", NULL },
+ { "1e12x", NULL },
+ { ".12x", NULL },
+ { "000", NULL },
+};
+
+static void test_pairs() {
+ int i;
+
+ for (i = 0; i < GPR_ARRAY_SIZE(testing_pairs); i++) {
+ testing_pair* pair = testing_pairs + i;
+ char* scratchpad = gpr_strdup(pair->input);
+ grpc_json* json;
+
+ gpr_log(GPR_INFO, "parsing string %i - should %s", i,
+ pair->output ? "succeed" : "fail");
+ json = grpc_json_parse_string(scratchpad);
+
+ if (pair->output) {
+ char* output;
+
+ GPR_ASSERT(json);
+ output = grpc_json_dump_to_string(json, 0);
+ GPR_ASSERT(output);
+ gpr_log(GPR_INFO, "succeeded with output = %s", output);
+ GPR_ASSERT(strcmp(output, pair->output) == 0);
+
+ grpc_json_destroy(json);
+ gpr_free(output);
+ } else {
+ gpr_log(GPR_INFO, "failed");
+ GPR_ASSERT(!json);
+ }
+
+ free(scratchpad);
+ }
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ test_pairs();
+ gpr_log(GPR_INFO, "json_test success");
+ return 0;
+}
diff --git a/test/core/json/rewrite_test_input.json b/test/core/json/rewrite_test_input.json
new file mode 100644
index 0000000000..568891474f
--- /dev/null
+++ b/test/core/json/rewrite_test_input.json
@@ -0,0 +1,203 @@
+{
+"unicode, escape and empty test": { "a\tb": "\u00eb", "empty": [{},[],{}] },
+"some more unicode tests": {
+ "typical utf-8 input (plane 0)": "รŸรขรฑฤ‡โ‡’",
+ "atypical utf-8 input (plane 1)": "๐„ž"
+},
+
+"whitespace test": { "trying" :
+"to"
+ ,
+
+ "break"
+ :
+ "the" ,
+ "parser": "a bit" } ,
+
+"#": "All these examples are from http://json.org/example",
+"test1":
+{
+ "glossary": {
+ "title": "example glossary",
+ "GlossDiv": {
+ "title": "S",
+ "GlossList": {
+ "GlossEntry": {
+ "ID": "SGML",
+ "SortAs": "SGML",
+ "GlossTerm": "Standard Generalized Markup Language",
+ "Acronym": "SGML",
+ "Abbrev": "ISO 8879:1986",
+ "GlossDef": {
+ "para": "A meta-markup language, used to create markup languages such as DocBook.",
+ "GlossSeeAlso": ["GML", "XML"]
+ },
+ "GlossSee": "markup"
+ }
+ }
+ }
+ }
+},
+
+"test2":
+{"menu": {
+ "id": "file",
+ "value": "File",
+ "popup": {
+ "menuitem": [
+ {"value": "New", "onclick": "CreateNewDoc()"},
+ {"value": "Open", "onclick": "OpenDoc()"},
+ {"value": "Close", "onclick": "CloseDoc()"}
+ ]
+ }
+}},
+
+"test3":
+{"widget": {
+ "debug": "on",
+ "window": {
+ "title": "Sample Konfabulator Widget",
+ "name": "main_window",
+ "width": 500,
+ "height": 500
+ },
+ "image": {
+ "src": "Images/Sun.png",
+ "name": "sun1",
+ "hOffset": 250,
+ "vOffset": 250,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Here",
+ "size": 36,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 250,
+ "vOffset": 100,
+ "alignment": "center",
+ "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+ }
+}},
+
+"test4":
+{"web-app": {
+ "servlet": [
+ {
+ "servlet-name": "cofaxCDS",
+ "servlet-class": "org.cofax.cds.CDSServlet",
+ "init-param": {
+ "configGlossary:installationAt": "Philadelphia, PA",
+ "configGlossary:adminEmail": "ksm@pobox.com",
+ "configGlossary:poweredBy": "Cofax",
+ "configGlossary:poweredByIcon": "/images/cofax.gif",
+ "configGlossary:staticPath": "/content/static",
+ "templateProcessorClass": "org.cofax.WysiwygTemplate",
+ "templateLoaderClass": "org.cofax.FilesTemplateLoader",
+ "templatePath": "templates",
+ "templateOverridePath": "",
+ "defaultListTemplate": "listTemplate.htm",
+ "defaultFileTemplate": "articleTemplate.htm",
+ "useJSP": false,
+ "jspListTemplate": "listTemplate.jsp",
+ "jspFileTemplate": "articleTemplate.jsp",
+ "cachePackageTagsTrack": 200,
+ "cachePackageTagsStore": 200,
+ "cachePackageTagsRefresh": 60,
+ "cacheTemplatesTrack": 100,
+ "cacheTemplatesStore": 50,
+ "cacheTemplatesRefresh": 15,
+ "cachePagesTrack": 200,
+ "cachePagesStore": 100,
+ "cachePagesRefresh": 10,
+ "cachePagesDirtyRead": 10,
+ "searchEngineListTemplate": "forSearchEnginesList.htm",
+ "searchEngineFileTemplate": "forSearchEngines.htm",
+ "searchEngineRobotsDb": "WEB-INF/robots.db",
+ "useDataStore": true,
+ "dataStoreClass": "org.cofax.SqlDataStore",
+ "redirectionClass": "org.cofax.SqlRedirection",
+ "dataStoreName": "cofax",
+ "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+ "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
+ "dataStoreUser": "sa",
+ "dataStorePassword": "dataStoreTestQuery",
+ "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
+ "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
+ "dataStoreInitConns": 10,
+ "dataStoreMaxConns": 100,
+ "dataStoreConnUsageLimit": 100,
+ "dataStoreLogLevel": "debug",
+ "maxUrlLength": 500}},
+ {
+ "servlet-name": "cofaxEmail",
+ "servlet-class": "org.cofax.cds.EmailServlet",
+ "init-param": {
+ "mailHost": "mail1",
+ "mailHostOverride": "mail2"}},
+ {
+ "servlet-name": "cofaxAdmin",
+ "servlet-class": "org.cofax.cds.AdminServlet"},
+
+ {
+ "servlet-name": "fileServlet",
+ "servlet-class": "org.cofax.cds.FileServlet"},
+ {
+ "servlet-name": "cofaxTools",
+ "servlet-class": "org.cofax.cms.CofaxToolsServlet",
+ "init-param": {
+ "templatePath": "toolstemplates/",
+ "log": 1,
+ "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
+ "logMaxSize": "",
+ "dataLog": 1,
+ "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
+ "dataLogMaxSize": "",
+ "removePageCache": "/content/admin/remove?cache=pages&id=",
+ "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
+ "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
+ "lookInContext": 1,
+ "adminGroupID": 4,
+ "betaServer": true}}],
+ "servlet-mapping": {
+ "cofaxCDS": "/",
+ "cofaxEmail": "/cofaxutil/aemail/*",
+ "cofaxAdmin": "/admin/*",
+ "fileServlet": "/static/*",
+ "cofaxTools": "/tools/*"},
+
+ "taglib": {
+ "taglib-uri": "cofax.tld",
+ "taglib-location": "/WEB-INF/tlds/cofax.tld"}}},
+
+"test5":
+{"menu": {
+ "header": "SVG Viewer",
+ "items": [
+ {"id": "Open"},
+ {"id": "OpenNew", "label": "Open New"},
+ null,
+ {"id": "ZoomIn", "label": "Zoom In"},
+ {"id": "ZoomOut", "label": "Zoom Out"},
+ {"id": "OriginalView", "label": "Original View"},
+ null,
+ {"id": "Quality"},
+ {"id": "Pause"},
+ {"id": "Mute"},
+ null,
+ {"id": "Find", "label": "Find..."},
+ {"id": "FindAgain", "label": "Find Again"},
+ {"id": "Copy"},
+ {"id": "CopyAgain", "label": "Copy Again"},
+ {"id": "CopySVG", "label": "Copy SVG"},
+ {"id": "ViewSVG", "label": "View SVG"},
+ {"id": "ViewSource", "label": "View Source"},
+ {"id": "SaveAs", "label": "Save As"},
+ null,
+ {"id": "Help"},
+ {"id": "About", "label": "About Adobe CVG Viewer..."}
+ ]
+}}
+
+
+}
diff --git a/test/core/json/rewrite_test_output_condensed.json b/test/core/json/rewrite_test_output_condensed.json
new file mode 100644
index 0000000000..e32603f470
--- /dev/null
+++ b/test/core/json/rewrite_test_output_condensed.json
@@ -0,0 +1 @@
+{"unicode, escape and empty test":{"a\tb":"\u00eb","empty":[{},[],{}]},"some more unicode tests":{"typical utf-8 input (plane 0)":"\u00df\u00e2\u00f1\u0107\u21d2","atypical utf-8 input (plane 1)":"\ud834\udd1e"},"whitespace test":{"trying":"to","break":"the","parser":"a bit"},"#":"All these examples are from http://json.org/example","test1":{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}},"test2":{"menu":{"id":"file","value":"File","popup":{"menuitem":[{"value":"New","onclick":"CreateNewDoc()"},{"value":"Open","onclick":"OpenDoc()"},{"value":"Close","onclick":"CloseDoc()"}]}}},"test3":{"widget":{"debug":"on","window":{"title":"Sample Konfabulator Widget","name":"main_window","width":50,"height":50},"image":{"src":"Images/Sun.png","name":"sun1","hOffset":25,"vOffset":25,"alignment":"center"},"text":{"data":"Click Here","size":3,"style":"bold","name":"text1","hOffset":25,"vOffset":10,"alignment":"center","onMouseUp":"sun1.opacity = (sun1.opacity / 100) * 90;"}}},"test4":{"web-app":{"servlet":[{"servlet-name":"cofaxCDS","servlet-class":"org.cofax.cds.CDSServlet","init-param":{"configGlossary:installationAt":"Philadelphia, PA","configGlossary:adminEmail":"ksm@pobox.com","configGlossary:poweredBy":"Cofax","configGlossary:poweredByIcon":"/images/cofax.gif","configGlossary:staticPath":"/content/static","templateProcessorClass":"org.cofax.WysiwygTemplate","templateLoaderClass":"org.cofax.FilesTemplateLoader","templatePath":"templates","templateOverridePath":"","defaultListTemplate":"listTemplate.htm","defaultFileTemplate":"articleTemplate.htm","useJSP":false,"jspListTemplate":"listTemplate.jsp","jspFileTemplate":"articleTemplate.jsp","cachePackageTagsTrack":20,"cachePackageTagsStore":20,"cachePackageTagsRefresh":6,"cacheTemplatesTrack":10,"cacheTemplatesStore":5,"cacheTemplatesRefresh":1,"cachePagesTrack":20,"cachePagesStore":10,"cachePagesRefresh":1,"cachePagesDirtyRead":1,"searchEngineListTemplate":"forSearchEnginesList.htm","searchEngineFileTemplate":"forSearchEngines.htm","searchEngineRobotsDb":"WEB-INF/robots.db","useDataStore":true,"dataStoreClass":"org.cofax.SqlDataStore","redirectionClass":"org.cofax.SqlRedirection","dataStoreName":"cofax","dataStoreDriver":"com.microsoft.jdbc.sqlserver.SQLServerDriver","dataStoreUrl":"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon","dataStoreUser":"sa","dataStorePassword":"dataStoreTestQuery","dataStoreTestQuery":"SET NOCOUNT ON;select test='test';","dataStoreLogFile":"/usr/local/tomcat/logs/datastore.log","dataStoreInitConns":1,"dataStoreMaxConns":10,"dataStoreConnUsageLimit":10,"dataStoreLogLevel":"debug","maxUrlLength":50}},{"servlet-name":"cofaxEmail","servlet-class":"org.cofax.cds.EmailServlet","init-param":{"mailHost":"mail1","mailHostOverride":"mail2"}},{"servlet-name":"cofaxAdmin","servlet-class":"org.cofax.cds.AdminServlet"},{"servlet-name":"fileServlet","servlet-class":"org.cofax.cds.FileServlet"},{"servlet-name":"cofaxTools","servlet-class":"org.cofax.cms.CofaxToolsServlet","init-param":{"templatePath":"toolstemplates/","log":,"logLocation":"/usr/local/tomcat/logs/CofaxTools.log","logMaxSize":"","dataLog":,"dataLogLocation":"/usr/local/tomcat/logs/dataLog.log","dataLogMaxSize":"","removePageCache":"/content/admin/remove?cache=pages&id=","removeTemplateCache":"/content/admin/remove?cache=templates&id=","fileTransferFolder":"/usr/local/tomcat/webapps/content/fileTransferFolder","lookInContext":,"adminGroupID":,"betaServer":true}}],"servlet-mapping":{"cofaxCDS":"/","cofaxEmail":"/cofaxutil/aemail/*","cofaxAdmin":"/admin/*","fileServlet":"/static/*","cofaxTools":"/tools/*"},"taglib":{"taglib-uri":"cofax.tld","taglib-location":"/WEB-INF/tlds/cofax.tld"}}},"test5":{"menu":{"header":"SVG Viewer","items":[{"id":"Open"},{"id":"OpenNew","label":"Open New"},null,{"id":"ZoomIn","label":"Zoom In"},{"id":"ZoomOut","label":"Zoom Out"},{"id":"OriginalView","label":"Original View"},null,{"id":"Quality"},{"id":"Pause"},{"id":"Mute"},null,{"id":"Find","label":"Find..."},{"id":"FindAgain","label":"Find Again"},{"id":"Copy"},{"id":"CopyAgain","label":"Copy Again"},{"id":"CopySVG","label":"Copy SVG"},{"id":"ViewSVG","label":"View SVG"},{"id":"ViewSource","label":"View Source"},{"id":"SaveAs","label":"Save As"},null,{"id":"Help"},{"id":"About","label":"About Adobe CVG Viewer..."}]}}} \ No newline at end of file
diff --git a/test/core/json/rewrite_test_output_indented.json b/test/core/json/rewrite_test_output_indented.json
new file mode 100644
index 0000000000..fdc6d4ca56
--- /dev/null
+++ b/test/core/json/rewrite_test_output_indented.json
@@ -0,0 +1,272 @@
+{
+ "unicode, escape and empty test": {
+ "a\tb": "\u00eb",
+ "empty": [
+ {},
+ [],
+ {}
+ ]
+ },
+ "some more unicode tests": {
+ "typical utf-8 input (plane 0)": "\u00df\u00e2\u00f1\u0107\u21d2",
+ "atypical utf-8 input (plane 1)": "\ud834\udd1e"
+ },
+ "whitespace test": {
+ "trying": "to",
+ "break": "the",
+ "parser": "a bit"
+ },
+ "#": "All these examples are from http://json.org/example",
+ "test1": {
+ "glossary": {
+ "title": "example glossary",
+ "GlossDiv": {
+ "title": "S",
+ "GlossList": {
+ "GlossEntry": {
+ "ID": "SGML",
+ "SortAs": "SGML",
+ "GlossTerm": "Standard Generalized Markup Language",
+ "Acronym": "SGML",
+ "Abbrev": "ISO 8879:1986",
+ "GlossDef": {
+ "para": "A meta-markup language, used to create markup languages such as DocBook.",
+ "GlossSeeAlso": [
+ "GML",
+ "XML"
+ ]
+ },
+ "GlossSee": "markup"
+ }
+ }
+ }
+ }
+ },
+ "test2": {
+ "menu": {
+ "id": "file",
+ "value": "File",
+ "popup": {
+ "menuitem": [
+ {
+ "value": "New",
+ "onclick": "CreateNewDoc()"
+ },
+ {
+ "value": "Open",
+ "onclick": "OpenDoc()"
+ },
+ {
+ "value": "Close",
+ "onclick": "CloseDoc()"
+ }
+ ]
+ }
+ }
+ },
+ "test3": {
+ "widget": {
+ "debug": "on",
+ "window": {
+ "title": "Sample Konfabulator Widget",
+ "name": "main_window",
+ "width": 50,
+ "height": 50
+ },
+ "image": {
+ "src": "Images/Sun.png",
+ "name": "sun1",
+ "hOffset": 25,
+ "vOffset": 25,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Here",
+ "size": 3,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 25,
+ "vOffset": 10,
+ "alignment": "center",
+ "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+ }
+ }
+ },
+ "test4": {
+ "web-app": {
+ "servlet": [
+ {
+ "servlet-name": "cofaxCDS",
+ "servlet-class": "org.cofax.cds.CDSServlet",
+ "init-param": {
+ "configGlossary:installationAt": "Philadelphia, PA",
+ "configGlossary:adminEmail": "ksm@pobox.com",
+ "configGlossary:poweredBy": "Cofax",
+ "configGlossary:poweredByIcon": "/images/cofax.gif",
+ "configGlossary:staticPath": "/content/static",
+ "templateProcessorClass": "org.cofax.WysiwygTemplate",
+ "templateLoaderClass": "org.cofax.FilesTemplateLoader",
+ "templatePath": "templates",
+ "templateOverridePath": "",
+ "defaultListTemplate": "listTemplate.htm",
+ "defaultFileTemplate": "articleTemplate.htm",
+ "useJSP": false,
+ "jspListTemplate": "listTemplate.jsp",
+ "jspFileTemplate": "articleTemplate.jsp",
+ "cachePackageTagsTrack": 20,
+ "cachePackageTagsStore": 20,
+ "cachePackageTagsRefresh": 6,
+ "cacheTemplatesTrack": 10,
+ "cacheTemplatesStore": 5,
+ "cacheTemplatesRefresh": 1,
+ "cachePagesTrack": 20,
+ "cachePagesStore": 10,
+ "cachePagesRefresh": 1,
+ "cachePagesDirtyRead": 1,
+ "searchEngineListTemplate": "forSearchEnginesList.htm",
+ "searchEngineFileTemplate": "forSearchEngines.htm",
+ "searchEngineRobotsDb": "WEB-INF/robots.db",
+ "useDataStore": true,
+ "dataStoreClass": "org.cofax.SqlDataStore",
+ "redirectionClass": "org.cofax.SqlRedirection",
+ "dataStoreName": "cofax",
+ "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+ "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
+ "dataStoreUser": "sa",
+ "dataStorePassword": "dataStoreTestQuery",
+ "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
+ "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
+ "dataStoreInitConns": 1,
+ "dataStoreMaxConns": 10,
+ "dataStoreConnUsageLimit": 10,
+ "dataStoreLogLevel": "debug",
+ "maxUrlLength": 50
+ }
+ },
+ {
+ "servlet-name": "cofaxEmail",
+ "servlet-class": "org.cofax.cds.EmailServlet",
+ "init-param": {
+ "mailHost": "mail1",
+ "mailHostOverride": "mail2"
+ }
+ },
+ {
+ "servlet-name": "cofaxAdmin",
+ "servlet-class": "org.cofax.cds.AdminServlet"
+ },
+ {
+ "servlet-name": "fileServlet",
+ "servlet-class": "org.cofax.cds.FileServlet"
+ },
+ {
+ "servlet-name": "cofaxTools",
+ "servlet-class": "org.cofax.cms.CofaxToolsServlet",
+ "init-param": {
+ "templatePath": "toolstemplates/",
+ "log": ,
+ "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
+ "logMaxSize": "",
+ "dataLog": ,
+ "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
+ "dataLogMaxSize": "",
+ "removePageCache": "/content/admin/remove?cache=pages&id=",
+ "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
+ "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
+ "lookInContext": ,
+ "adminGroupID": ,
+ "betaServer": true
+ }
+ }
+ ],
+ "servlet-mapping": {
+ "cofaxCDS": "/",
+ "cofaxEmail": "/cofaxutil/aemail/*",
+ "cofaxAdmin": "/admin/*",
+ "fileServlet": "/static/*",
+ "cofaxTools": "/tools/*"
+ },
+ "taglib": {
+ "taglib-uri": "cofax.tld",
+ "taglib-location": "/WEB-INF/tlds/cofax.tld"
+ }
+ }
+ },
+ "test5": {
+ "menu": {
+ "header": "SVG Viewer",
+ "items": [
+ {
+ "id": "Open"
+ },
+ {
+ "id": "OpenNew",
+ "label": "Open New"
+ },
+ null,
+ {
+ "id": "ZoomIn",
+ "label": "Zoom In"
+ },
+ {
+ "id": "ZoomOut",
+ "label": "Zoom Out"
+ },
+ {
+ "id": "OriginalView",
+ "label": "Original View"
+ },
+ null,
+ {
+ "id": "Quality"
+ },
+ {
+ "id": "Pause"
+ },
+ {
+ "id": "Mute"
+ },
+ null,
+ {
+ "id": "Find",
+ "label": "Find..."
+ },
+ {
+ "id": "FindAgain",
+ "label": "Find Again"
+ },
+ {
+ "id": "Copy"
+ },
+ {
+ "id": "CopyAgain",
+ "label": "Copy Again"
+ },
+ {
+ "id": "CopySVG",
+ "label": "Copy SVG"
+ },
+ {
+ "id": "ViewSVG",
+ "label": "View SVG"
+ },
+ {
+ "id": "ViewSource",
+ "label": "View Source"
+ },
+ {
+ "id": "SaveAs",
+ "label": "Save As"
+ },
+ null,
+ {
+ "id": "Help"
+ },
+ {
+ "id": "About",
+ "label": "About Adobe CVG Viewer..."
+ }
+ ]
+ }
+ }
+} \ No newline at end of file