diff --git a/.gitignore b/.gitignore index 6dfd3fd..6da095d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ /configure /depcomp /install-sh -/json.pc +/json-c.pc /libtool /ltmain.sh /Makefile diff --git a/Makefile.am b/Makefile.am index f2d708a..868cf97 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,12 +3,12 @@ include Makefile.am.inc EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc json-c.vcproj SUBDIRS = . tests -lib_LTLIBRARIES = libjson.la +lib_LTLIBRARIES = libjson-c.la pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = json.pc +pkgconfig_DATA = json-c.pc -libjsonincludedir = $(includedir)/json +libjsonincludedir = $(includedir)/json-c libjsoninclude_HEADERS = \ arraylist.h \ bits.h \ @@ -29,9 +29,9 @@ libjsoninclude_HEADERS = \ #libjsonx_include_HEADERS = \ # json_config.h -libjson_la_LDFLAGS = -version-info 1:0:1 -no-undefined +libjson_c_la_LDFLAGS = -version-info 1:0:1 -no-undefined -libjson_la_SOURCES = \ +libjson_c_la_SOURCES = \ arraylist.c \ debug.c \ json_object.c \ diff --git a/configure.in b/configure.in index f8f929e..79eafd1 100644 --- a/configure.in +++ b/configure.in @@ -33,7 +33,7 @@ AM_PROG_LIBTOOL AC_CONFIG_FILES([ Makefile -json.pc +json-c.pc tests/Makefile json-uninstalled.pc ]) diff --git a/json.pc.in b/json-c.pc.in similarity index 67% rename from json.pc.in rename to json-c.pc.in index b3d140b..037739d 100644 --- a/json.pc.in +++ b/json-c.pc.in @@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: json +Name: json-c Description: JSON implementation in C Version: @VERSION@ Requires: -Libs: -L${libdir} -ljson -Cflags: -I${includedir}/json +Libs: -L${libdir} -ljson-c +Cflags: -I${includedir}/json-c diff --git a/test_parse.c b/test_parse.c new file mode 100644 index 0000000..0040760 --- /dev/null +++ b/test_parse.c @@ -0,0 +1,270 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "json_tokener.h" + +static void test_basic_parse(void); +static void test_verbose_parse(void); +static void test_incremental_parse(void); + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + test_basic_parse(); + printf("==================================\n"); + test_verbose_parse(); + printf("==================================\n"); + test_incremental_parse(); + printf("==================================\n"); +} + +static void test_basic_parse() +{ + json_object *new_obj; + + new_obj = json_tokener_parse("\"\003\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("/* hello */\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("// hello\n\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("null"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("True"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12.3"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\nabc\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[null]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[false]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{}"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\" }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); +} + +static void test_verbose_parse() +{ + json_object *new_obj; + enum json_tokener_error error = json_tokener_success; + + new_obj = json_tokener_parse_verbose("{ foo }", &error); + assert (error == json_tokener_error_parse_object_key_name); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("{ foo }"); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("foo"); + assert (new_obj == NULL); + new_obj = json_tokener_parse_verbose("foo", &error); + assert (new_obj == NULL); + + /* b/c the string starts with 'f' parsing return a boolean error */ + assert (error == json_tokener_error_parse_boolean); + + printf("json_tokener_parse_versbose() OK\n"); +} + +struct incremental_step { + const char *string_to_parse; + int length; + int char_offset; + enum json_tokener_error expected_error; + int reset_tokener; +} incremental_steps[] = { + + /* Check that full json messages can be parsed, both w/ and w/o a reset */ + { "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 }, + { "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 }, + { "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 }, + + /* Check a basic incremental parse */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}", -1, -1, json_tokener_success, 1 }, + + /* Check that json_tokener_reset actually resets */ + { "{ \"foo", -1, -1, json_tokener_continue, 1 }, + { ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check incremental parsing with trailing characters */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}XXXX", 10, 6, json_tokener_success, 0 }, + { "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check that trailing characters can change w/o a reset */ + { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 }, + { "\"Y\"", -1, -1, json_tokener_success, 1 }, + + /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */ + { "1", 1, 1, json_tokener_continue, 0 }, + { "2", 2, 1, json_tokener_success, 0 }, + + /* Strings have a well defined end point, so we can stop at the quote */ + { "\"blue\"", -1, -1, json_tokener_success, 0 }, + + { "[1,2,3]", -1, -1, json_tokener_success, 0 }, + + /* This behaviour doesn't entirely follow the json spec, but until we have + a way to specify how strict to be we follow Postel's Law and be liberal + in what we accept (up to a point). */ + { "[1,2,3,]", -1, -1, json_tokener_success, 0 }, + { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, + + { NULL, json_tokener_success }, +}; + +static void test_incremental_parse() +{ + json_object *new_obj; + enum json_tokener_error jerr; + json_tokener *tok; + const char *string_to_parse; + int ii; + int num_ok, num_error; + + num_ok = 0; + num_error = 0; + + printf("Starting incremental tests.\n"); + + string_to_parse = "{ \"foo"; /* } */ + printf("json_tokener_parse(%s) ... ", string_to_parse); + new_obj = json_tokener_parse(string_to_parse); + if (new_obj == NULL) printf("got error as expected\n"); + + /* test incremental parsing in various forms */ + tok = json_tokener_new(); + for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++) + { + int this_step_ok = 0; + struct incremental_step *step = &incremental_steps[ii]; + int length = step->length; + int expected_char_offset = step->char_offset; + if (length == -1) + length = strlen(step->string_to_parse); + if (expected_char_offset == -1) + expected_char_offset = length; + + printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", + step->string_to_parse, length); + new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); + + jerr = json_tokener_get_error(tok); + if (step->expected_error != json_tokener_success) + { + if (new_obj != NULL) + printf("ERROR: invalid object returned: %s\n", + json_object_to_json_string(new_obj)); + else if (jerr != step->expected_error) + printf("ERROR: got wrong error: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr)); + this_step_ok = 1; + } + } + else + { + if (new_obj == NULL) + printf("ERROR: expected valid object, instead: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got object of type [%s]: %s\n", + json_type_to_name(json_object_get_type(new_obj)), + json_object_to_json_string(new_obj)); + this_step_ok = 1; + } + } + + if (new_obj) + json_object_put(new_obj); + + if (step->reset_tokener) + json_tokener_reset(tok); + + if (this_step_ok) + num_ok++; + else + num_error++; + } + + json_tokener_free(tok); + + printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error); + + return; +} diff --git a/test_parse.expected b/test_parse.expected new file mode 100644 index 0000000..2481bde --- /dev/null +++ b/test_parse.expected @@ -0,0 +1,46 @@ +new_obj.to_string()="\u0003" +new_obj.to_string()="foo" +new_obj.to_string()="foo" +new_obj.to_string()="ABC" +new_obj.to_string()=null +new_obj.to_string()=true +new_obj.to_string()=12 +new_obj.to_string()=12.300000 +new_obj.to_string()=[ "\n" ] +new_obj.to_string()=[ "\nabc\n" ] +new_obj.to_string()=[ null ] +new_obj.to_string()=[ ] +new_obj.to_string()=[ false ] +new_obj.to_string()=[ "abc", null, "def", 12 ] +new_obj.to_string()={ } +new_obj.to_string()={ "foo": "bar" } +new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true } +new_obj.to_string()={ "foo": [ null, "foo" ] } +new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] } +================================== +json_tokener_parse_versbose() OK +================================== +Starting incremental tests. +json_tokener_parse({ "foo) ... got error as expected +json_tokener_parse_ex(tok, { "foo": 123 }, 14) ... OK: got object of type [object]: { "foo": 123 } +json_tokener_parse_ex(tok, { "foo": 456 }, 14) ... OK: got object of type [object]: { "foo": 456 } +json_tokener_parse_ex(tok, { "foo": 789 }, 14) ... OK: got object of type [object]: { "foo": 789 } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}} , 6) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, XXXX , 4) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, {"x": 123 }"X", 14) ... OK: got object of type [object]: { "x": 123 } +json_tokener_parse_ex(tok, "Y" , 3) ... OK: got object of type [string]: "Y" +json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue +json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12 +json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue" +json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character +End Incremental Tests OK=20 ERROR=0 +================================== diff --git a/test_parse.test b/test_parse.test new file mode 100755 index 0000000..70d1c82 --- /dev/null +++ b/test_parse.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_parse +exit $?