From 4146070e69475d5eedcf7a9e3d990e511f46ec7a Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Tue, 3 May 2011 23:04:22 +0930 Subject: Add basic JSON tests and benchmark --- tests/README | 2 + tests/bench.lua | 39 ++++++++++++++ tests/common.lua | 79 +++++++++++++++++++++++++++++ tests/example1.json | 24 +++++++++ tests/example2.json | 11 ++++ tests/example3.json | 26 ++++++++++ tests/example4.json | 90 +++++++++++++++++++++++++++++++++ tests/example5.json | 27 ++++++++++ tests/rfc-example1.json | 13 +++++ tests/rfc-example2.json | 22 ++++++++ tests/test.lua | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 465 insertions(+) create mode 100644 tests/README create mode 100755 tests/bench.lua create mode 100644 tests/common.lua create mode 100644 tests/example1.json create mode 100644 tests/example2.json create mode 100644 tests/example3.json create mode 100644 tests/example4.json create mode 100644 tests/example5.json create mode 100644 tests/rfc-example1.json create mode 100644 tests/rfc-example2.json create mode 100755 tests/test.lua diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..58e7655 --- /dev/null +++ b/tests/README @@ -0,0 +1,2 @@ +These JSON examples were taken from the JSON website +(http://json.org/example.html) and RFC 4627. diff --git a/tests/bench.lua b/tests/bench.lua new file mode 100755 index 0000000..b5b1a77 --- /dev/null +++ b/tests/bench.lua @@ -0,0 +1,39 @@ +#!/usr/bin/env lua + +-- Simple JSON benchmark. +-- +-- Your Mileage May Vary. + +require "common" +local json = require "cjson" +--local json = require "json" +--local json = require "dkjson" + +function bench_file(filename) + local data_json = file_load(filename) + local data_obj = json.decode(data_json) + + local function test_encode () + json.encode(data_obj) + end + local function test_decode () + json.decode(data_json) + end + + local tests = { + encode = test_encode, + decode = test_decode + } + + return benchmark(tests, 5000, 5) +end + +i = 1 +while arg[i] do + local results = {} + results[arg[i]] = bench_file(arg[i]) + dump_value(results) + i = i + 1 +end + +-- vi:ai et sw=4 ts=4: diff --git a/tests/common.lua b/tests/common.lua new file mode 100644 index 0000000..e935032 --- /dev/null +++ b/tests/common.lua @@ -0,0 +1,79 @@ +require "cjson" +require "posix" + +function dump_value(value, indent) + if indent == nil then + indent = "" + end + + if value == cjson.null then + value = "" + end + + if type(value) == "string" or type(value) == "number" or + type(value) == "boolean" then + print(indent .. tostring(value)) + elseif type(value) == "table" then + local count = 0 + for k, v in pairs(value) do + dump_value(v, indent .. k .. ": ") + count = count + 1 + end + if count == 0 then + print(indent .. ": ") + end + else + print(indent .. "<" .. type(value) .. ">") + end + +end + +function file_load(filename) + local file, err = io.open(filename) + if file == nil then + error("Unable to read " .. filename) + end + local data = file:read("*a") + file:close() + + return data +end + +function gettimeofday() + local tv_sec, tv_usec = posix.gettimeofday() + + return tv_sec + tv_usec / 1000000 +end + +function benchmark(tests, iter, rep) + local function bench(func, iter) + collectgarbage("collect") + local t = gettimeofday() + for i = 1, iter do + func(i) + end + t = gettimeofday() - t + return (iter / t) + end + + local test_results = {} + for name, func in pairs(tests) do + -- k(number), v(string) + -- k(string), v(function) + -- k(number), v(function) + if type(func) == "string" then + name = func + func = _G[name] + end + local result = {} + for i = 1, rep do + result[i] = bench(func, iter) + end + table.sort(result) + test_results[name] = result[rep] + end + + return test_results +end + +-- vi:ai et sw=4 ts=4: diff --git a/tests/example1.json b/tests/example1.json new file mode 100644 index 0000000..53ec437 --- /dev/null +++ b/tests/example1.json @@ -0,0 +1,24 @@ +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Mark +up 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" + } + } + } + } +} diff --git a/tests/example2.json b/tests/example2.json new file mode 100644 index 0000000..5600991 --- /dev/null +++ b/tests/example2.json @@ -0,0 +1,11 @@ +{"menu": { + "id": "file", + "value": "File", + "popup": { + "menuitem": [ + {"value": "New", "onclick": "CreateNewDoc()"}, + {"value": "Open", "onclick": "OpenDoc()"}, + {"value": "Close", "onclick": "CloseDoc()"} + ] + } +}} diff --git a/tests/example3.json b/tests/example3.json new file mode 100644 index 0000000..d7237a5 --- /dev/null +++ b/tests/example3.json @@ -0,0 +1,26 @@ +{"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;" + } +}} diff --git a/tests/example4.json b/tests/example4.json new file mode 100644 index 0000000..16335b2 --- /dev/null +++ b/tests/example4.json @@ -0,0 +1,90 @@ +{"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/fileTransferFo +lder", + "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"}}} diff --git a/tests/example5.json b/tests/example5.json new file mode 100644 index 0000000..49980ca --- /dev/null +++ b/tests/example5.json @@ -0,0 +1,27 @@ +{"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/tests/rfc-example1.json b/tests/rfc-example1.json new file mode 100644 index 0000000..73532fa --- /dev/null +++ b/tests/rfc-example1.json @@ -0,0 +1,13 @@ +{ + "Image": { + "Width": 800, + "Height": 600, + "Title": "View from 15th Floor", + "Thumbnail": { + "Url": "http://www.example.com/image/481989943", + "Height": 125, + "Width": "100" + }, + "IDs": [116, 943, 234, 38793] + } +} diff --git a/tests/rfc-example2.json b/tests/rfc-example2.json new file mode 100644 index 0000000..2a0cb68 --- /dev/null +++ b/tests/rfc-example2.json @@ -0,0 +1,22 @@ +[ + { + "precision": "zip", + "Latitude": 37.7668, + "Longitude": -122.3959, + "Address": "", + "City": "SAN FRANCISCO", + "State": "CA", + "Zip": "94107", + "Country": "US" + }, + { + "precision": "zip", + "Latitude": 37.371991, + "Longitude": -122.026020, + "Address": "", + "City": "SUNNYVALE", + "State": "CA", + "Zip": "94085", + "Country": "US" + } +] diff --git a/tests/test.lua b/tests/test.lua new file mode 100755 index 0000000..9424e8f --- /dev/null +++ b/tests/test.lua @@ -0,0 +1,132 @@ +#!/usr/bin/env lua + +require "common" +local json = require "cjson" + +local cjson_test_non_default = true + +function run_tests(tests, func) + for k, v in ipairs(tests) do + local success, msg = pcall(func, v) + if not success then + print("Error: " .. msg) + end + print() + end +end + +local simple_value_tests = { + [[ "test string" ]], + [[ -5e3 ]], + [[ null ]], + [[ true ]], + [[ false ]], + [[ { "1": "one", "3": "three" } ]] +} + +local numeric_tests = { + "[ 0.0, -1, 0.3e-3, 1023.2 ]", + "[ 00123 ]", + "[ 05.2 ]", + "[ 0e10 ]", + "[ 0x6 ]", + "[ +Inf ]", + "[ Inf ]", + "[ -Inf ]", + "[ +Infinity ]", + "[ Infinity ]", + "[ -Infinity ]", + "[ +NaN ]", + "[ NaN ]", + "[ -NaN ]", + "[ Infrared ]", + "[ Noodle ]" +} + +local object_tests = { + { [5] = "sparse test" }, + { [6] = "sparse test" }, + {{{{{{{{{{{{{{{{{{{{{ "nested" }}}}}}}}}}}}}}}}}}}}} +} + +local decode_error_tests = { + '{ "unexpected eof": ', + '{ "extra data": true }, false', + [[ { "bad escape \q code" } ]], + [[ { "bad unicode \u0f6 escape" } ]], + [[ [ "bad barewood", test ] ]], + "[ -+12 ]", + "-v", + "[ 0.4eg10 ]", +} + +local simple_encode_tests = { + json.null, true, false, { }, 10, "hello" +} + + +local function gen_ascii(max) + local chars = {} + for i = 0, max do + chars[i] = string.char(i) + end + return table.concat(chars) +end + +local function decode_encode(text) + print("==JSON=> " .. text) + local obj_data = json.decode(text) + dump_value(obj_data) + local obj_json = json.encode(obj_data) + print(obj_json) +end +local function encode_decode(obj) + print("==OBJ==> ") + dump_value(obj) + local obj_json = json.encode(obj) + print(obj_json) + local obj_data = json.decode(obj_json) + dump_value(obj_data) +end + +run_tests(simple_value_tests, decode_encode) +run_tests(decode_error_tests, decode_encode) + +run_tests(numeric_tests, decode_encode) + +if cjson_test_non_default then + print("=== Disabling strict numbers ===") + json.strict_numbers(false) + run_tests(numeric_tests, decode_encode) + json.strict_numbers(true) +end + +run_tests(object_tests, encode_decode) +print ("Encode tests..") + +run_tests(simple_encode_tests, encode_decode) + +if cjson_test_non_default then + print("=== Setting max_depth to 21, sparse_ratio to 5 ===") + json.max_depth(21) + json.sparse_ratio(5) + run_tests(object_tests, encode_decode) +end + +local ascii1 = gen_ascii(255) +print("Unprintable escapes:") +print(json.encode(ascii1)) +print("===") +local ascii2 = json.decode(json.encode(ascii)) + +print("8bit clean encode/decode: " .. tostring(ascii1 ~= ascii2)) + +for i = 1, #arg do + print(arg[i] .. " enc->dec..") + local obj1 = json.decode(file_load(arg[i])) + local obj2 = json.decode(json.encode(obj1)) + -- obj_compare(obj_json1, obj_json2) + print(".. unimplemented") +end + +-- vi:ai et sw=4 ts=4: -- cgit v1.2.3-55-g6feb