From 1eab22f0da9054bac02fbe9d90499a3ee5e8e5b2 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 16 Jun 2017 10:50:49 +0300 Subject: [PATCH] tests: add test_deep_copy test Seems to perform better than outputting to string and re-parsing it. BENCHMARK - 1000000 iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took 20 seconds BENCHMARK - 1000000 iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took 7 seconds It should make a difference on embedded systems. The test was performed on a i5 desktop CPU [~3.5 years of age]. Signed-off-by: Alexandru Ardelean --- .gitignore | 1 + tests/Makefile.am | 1 + tests/test_deep_copy.c | 175 ++++++++++++++++++++++++++++++++++ tests/test_deep_copy.expected | 140 +++++++++++++++++++++++++++ tests/test_deep_copy.test | 1 + 5 files changed, 318 insertions(+) create mode 100644 tests/test_deep_copy.c create mode 100644 tests/test_deep_copy.expected create mode 120000 tests/test_deep_copy.test diff --git a/.gitignore b/.gitignore index 393b6eb3b3..c2b9b8999f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ /tests/test_cast /tests/test_charcase /tests/test_compare +/tests/test_deep_copy /tests/test_double_serializer /tests/test_float /tests/test_json_pointer diff --git a/tests/Makefile.am b/tests/Makefile.am index c6a298345a..014de6f4ac 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,6 +13,7 @@ TESTS+= test2.test TESTS+= test4.test TESTS+= testReplaceExisting.test TESTS+= test_parse_int64.test +TESTS+= test_deep_copy.test TESTS+= test_null.test TESTS+= test_cast.test TESTS+= test_double_serializer.test diff --git a/tests/test_deep_copy.c b/tests/test_deep_copy.c new file mode 100644 index 0000000000..78a346cba1 --- /dev/null +++ b/tests/test_deep_copy.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "json.h" + +static const char *json_str1 = +"{" +" \"glossary\": {" +" \"title\": \"example glossary\"," +" \"GlossDiv\": {" +" \"title\": \"S\"," +" \"null_obj\": null, " +" \"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\"" +" }" +" }" +" }" +" }" +"}"; + +static const char *json_str2 = +"{\"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\", \"another_null\": null}," +" {\"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...\"}" +" ]" +"}}"; + +static const char *json_str3 = +"{\"menu\": {" +" \"id\": \"file\"," +" \"value\": \"File\"," +" \"popup\": {" +" \"menuitem\": [" +" {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"}," +" {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"}," +" {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}" +" ]" +" }" +"}}"; + +int main(int argc, char **argv) +{ + struct json_object *src1, *src2, *src3; + struct json_object *dst1 = NULL, *dst2 = NULL, *dst3 = NULL; + + src1 = json_tokener_parse(json_str1); + src2 = json_tokener_parse(json_str2); + src3 = json_tokener_parse(json_str3); + + assert(src1 != NULL); + assert(src1 != NULL); + assert(src3 != NULL); + + printf("PASSED - loaded input data\n"); + + /* do this 3 times to make sure overwriting it works */ + assert(0 == json_object_deep_copy(src1, &dst1)); + assert(0 == json_object_deep_copy(src2, &dst2)); + assert(0 == json_object_deep_copy(src3, &dst3)); + + printf("PASSED - all json_object_deep_copy() returned succesful\n"); + + assert(-1 == json_object_deep_copy(src1, &dst1)); + assert(errno == EINVAL); + assert(-1 == json_object_deep_copy(src2, &dst2)); + assert(errno == EINVAL); + assert(-1 == json_object_deep_copy(src3, &dst3)); + assert(errno == EINVAL); + + printf("PASSED - all json_object_deep_copy() returned EINVAL for non-null pointer\n"); + + assert(1 == json_object_equal(src1, dst1)); + assert(1 == json_object_equal(src2, dst2)); + assert(1 == json_object_equal(src3, dst3)); + + printf("PASSED - all json_object_equal() tests returned succesful\n"); + + assert(0 == strcmp(json_object_to_json_string_ext(src1, JSON_C_TO_STRING_PRETTY), + json_object_to_json_string_ext(dst1, JSON_C_TO_STRING_PRETTY))); + assert(0 == strcmp(json_object_to_json_string_ext(src2, JSON_C_TO_STRING_PRETTY), + json_object_to_json_string_ext(dst2, JSON_C_TO_STRING_PRETTY))); + assert(0 == strcmp(json_object_to_json_string_ext(src3, JSON_C_TO_STRING_PRETTY), + json_object_to_json_string_ext(dst3, JSON_C_TO_STRING_PRETTY))); + + printf("PASSED - comparison of string output\n"); + + json_object_get(dst1); + assert(-1 == json_object_deep_copy(src1, &dst1)); + assert(errno == EINVAL); + + printf("PASSED - trying to overrwrite an object that has refcount > 1"); + + printf("\nPrinting JSON objects for visual inspection\n"); + printf("------------------------------------------------\n"); + printf(" JSON1\n"); + printf("%s", json_object_to_json_string_ext(dst1, JSON_C_TO_STRING_PRETTY)); + printf("------------------------------------------------\n"); + + printf("------------------------------------------------\n"); + printf(" JSON2\n"); + printf("%s", json_object_to_json_string_ext(dst2, JSON_C_TO_STRING_PRETTY)); + printf("------------------------------------------------\n"); + + printf("------------------------------------------------\n"); + printf(" JSON3\n"); + printf("------------------------------------------------\n"); + printf("%s", json_object_to_json_string_ext(dst3, JSON_C_TO_STRING_PRETTY)); + printf("------------------------------------------------\n"); + + json_object_put(dst1); + json_object_put(dst2); + json_object_put(dst3); + +#if BENCHMARK + /** + * The numbers that I got are: + * BENCHMARK - 1000000 iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took 20 seconds + * BENCHMARK - 1000000 iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took 7 seconds + */ + + int iterations = 1000000; + time_t start = time(NULL); + for (i = 0; i < iterations; i++) { + dst2 = json_tokener_parse(json_object_get_string(src2)); + json_object_put(dst2); + } + printf("BENCHMARK - %d iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took %d seconds\n", iterations, (int)(time(NULL) - start)); + + start = time(NULL); + for (i = 0; i < iterations; i++) { + json_object_deep_copy(src2, &dst2); + } + json_object_put(dst2); + printf("BENCHMARK - %d iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took %d seconds\n", iterations, (int)(time(NULL) - start)); +#endif + + return 0; +} diff --git a/tests/test_deep_copy.expected b/tests/test_deep_copy.expected new file mode 100644 index 0000000000..ce3358c282 --- /dev/null +++ b/tests/test_deep_copy.expected @@ -0,0 +1,140 @@ +PASSED - loaded input data +PASSED - all json_object_deep_copy() returned succesful +PASSED - all json_object_deep_copy() returned EINVAL for non-null pointer +PASSED - all json_object_equal() tests returned succesful +PASSED - comparison of string output +PASSED - trying to overrwrite an object that has refcount > 1 +Printing JSON objects for visual inspection +------------------------------------------------ + JSON1 +{ + "glossary":{ + "title":"example glossary", + "GlossDiv":{ + "title":"S", + "null_obj":null, + "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" + } + } + } + } +}------------------------------------------------ +------------------------------------------------ + JSON2 +{ + "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", + "another_null":null + }, + { + "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..." + } + ] + } +}------------------------------------------------ +------------------------------------------------ + JSON3 +------------------------------------------------ +{ + "menu":{ + "id":"file", + "value":"File", + "popup":{ + "menuitem":[ + { + "value":"New", + "onclick":"CreateNewDoc()" + }, + { + "value":"Open", + "onclick":"OpenDoc()" + }, + { + "value":"Close", + "onclick":"CloseDoc()" + } + ] + } + } +}------------------------------------------------ diff --git a/tests/test_deep_copy.test b/tests/test_deep_copy.test new file mode 120000 index 0000000000..58a13f4f32 --- /dev/null +++ b/tests/test_deep_copy.test @@ -0,0 +1 @@ +test_basic.test \ No newline at end of file