diff options
author | Mark Pulford <mark@kyne.com.au> | 2011-05-03 23:04:22 +0930 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2011-05-03 23:04:22 +0930 |
commit | 4146070e69475d5eedcf7a9e3d990e511f46ec7a (patch) | |
tree | 5e6bfa66ee9a1fc4ac4125f349c55a3d7c551e35 | |
parent | ce3a769dbdd13571b5b761d933e17e8fe5771739 (diff) | |
download | lua-cjson-4146070e69475d5eedcf7a9e3d990e511f46ec7a.tar.gz lua-cjson-4146070e69475d5eedcf7a9e3d990e511f46ec7a.tar.bz2 lua-cjson-4146070e69475d5eedcf7a9e3d990e511f46ec7a.zip |
Add basic JSON tests and benchmark
-rw-r--r-- | tests/README | 2 | ||||
-rwxr-xr-x | tests/bench.lua | 39 | ||||
-rw-r--r-- | tests/common.lua | 79 | ||||
-rw-r--r-- | tests/example1.json | 24 | ||||
-rw-r--r-- | tests/example2.json | 11 | ||||
-rw-r--r-- | tests/example3.json | 26 | ||||
-rw-r--r-- | tests/example4.json | 90 | ||||
-rw-r--r-- | tests/example5.json | 27 | ||||
-rw-r--r-- | tests/rfc-example1.json | 13 | ||||
-rw-r--r-- | tests/rfc-example2.json | 22 | ||||
-rwxr-xr-x | tests/test.lua | 132 |
11 files changed, 465 insertions, 0 deletions
diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..58e7655 --- /dev/null +++ b/tests/README | |||
@@ -0,0 +1,2 @@ | |||
1 | These JSON examples were taken from the JSON website | ||
2 | (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 @@ | |||
1 | #!/usr/bin/env lua | ||
2 | |||
3 | -- Simple JSON benchmark. | ||
4 | -- | ||
5 | -- Your Mileage May Vary. | ||
6 | |||
7 | require "common" | ||
8 | local json = require "cjson" | ||
9 | --local json = require "json" | ||
10 | --local json = require "dkjson" | ||
11 | |||
12 | function bench_file(filename) | ||
13 | local data_json = file_load(filename) | ||
14 | local data_obj = json.decode(data_json) | ||
15 | |||
16 | local function test_encode () | ||
17 | json.encode(data_obj) | ||
18 | end | ||
19 | local function test_decode () | ||
20 | json.decode(data_json) | ||
21 | end | ||
22 | |||
23 | local tests = { | ||
24 | encode = test_encode, | ||
25 | decode = test_decode | ||
26 | } | ||
27 | |||
28 | return benchmark(tests, 5000, 5) | ||
29 | end | ||
30 | |||
31 | i = 1 | ||
32 | while arg[i] do | ||
33 | local results = {} | ||
34 | results[arg[i]] = bench_file(arg[i]) | ||
35 | dump_value(results) | ||
36 | i = i + 1 | ||
37 | end | ||
38 | |||
39 | -- 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 @@ | |||
1 | require "cjson" | ||
2 | require "posix" | ||
3 | |||
4 | function dump_value(value, indent) | ||
5 | if indent == nil then | ||
6 | indent = "" | ||
7 | end | ||
8 | |||
9 | if value == cjson.null then | ||
10 | value = "<cjson.null>" | ||
11 | end | ||
12 | |||
13 | if type(value) == "string" or type(value) == "number" or | ||
14 | type(value) == "boolean" then | ||
15 | print(indent .. tostring(value)) | ||
16 | elseif type(value) == "table" then | ||
17 | local count = 0 | ||
18 | for k, v in pairs(value) do | ||
19 | dump_value(v, indent .. k .. ": ") | ||
20 | count = count + 1 | ||
21 | end | ||
22 | if count == 0 then | ||
23 | print(indent .. ": <empty>") | ||
24 | end | ||
25 | else | ||
26 | print(indent .. "<" .. type(value) .. ">") | ||
27 | end | ||
28 | |||
29 | end | ||
30 | |||
31 | function file_load(filename) | ||
32 | local file, err = io.open(filename) | ||
33 | if file == nil then | ||
34 | error("Unable to read " .. filename) | ||
35 | end | ||
36 | local data = file:read("*a") | ||
37 | file:close() | ||
38 | |||
39 | return data | ||
40 | end | ||
41 | |||
42 | function gettimeofday() | ||
43 | local tv_sec, tv_usec = posix.gettimeofday() | ||
44 | |||
45 | return tv_sec + tv_usec / 1000000 | ||
46 | end | ||
47 | |||
48 | function benchmark(tests, iter, rep) | ||
49 | local function bench(func, iter) | ||
50 | collectgarbage("collect") | ||
51 | local t = gettimeofday() | ||
52 | for i = 1, iter do | ||
53 | func(i) | ||
54 | end | ||
55 | t = gettimeofday() - t | ||
56 | return (iter / t) | ||
57 | end | ||
58 | |||
59 | local test_results = {} | ||
60 | for name, func in pairs(tests) do | ||
61 | -- k(number), v(string) | ||
62 | -- k(string), v(function) | ||
63 | -- k(number), v(function) | ||
64 | if type(func) == "string" then | ||
65 | name = func | ||
66 | func = _G[name] | ||
67 | end | ||
68 | local result = {} | ||
69 | for i = 1, rep do | ||
70 | result[i] = bench(func, iter) | ||
71 | end | ||
72 | table.sort(result) | ||
73 | test_results[name] = result[rep] | ||
74 | end | ||
75 | |||
76 | return test_results | ||
77 | end | ||
78 | |||
79 | -- 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 @@ | |||
1 | { | ||
2 | "glossary": { | ||
3 | "title": "example glossary", | ||
4 | "GlossDiv": { | ||
5 | "title": "S", | ||
6 | "GlossList": { | ||
7 | "GlossEntry": { | ||
8 | "ID": "SGML", | ||
9 | "SortAs": "SGML", | ||
10 | "GlossTerm": "Standard Generalized Mark | ||
11 | up Language", | ||
12 | "Acronym": "SGML", | ||
13 | "Abbrev": "ISO 8879:1986", | ||
14 | "GlossDef": { | ||
15 | "para": "A meta-markup language, used to create markup | ||
16 | languages such as DocBook.", | ||
17 | "GlossSeeAlso": ["GML", "XML"] | ||
18 | }, | ||
19 | "GlossSee": "markup" | ||
20 | } | ||
21 | } | ||
22 | } | ||
23 | } | ||
24 | } | ||
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 @@ | |||
1 | {"menu": { | ||
2 | "id": "file", | ||
3 | "value": "File", | ||
4 | "popup": { | ||
5 | "menuitem": [ | ||
6 | {"value": "New", "onclick": "CreateNewDoc()"}, | ||
7 | {"value": "Open", "onclick": "OpenDoc()"}, | ||
8 | {"value": "Close", "onclick": "CloseDoc()"} | ||
9 | ] | ||
10 | } | ||
11 | }} | ||
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 @@ | |||
1 | {"widget": { | ||
2 | "debug": "on", | ||
3 | "window": { | ||
4 | "title": "Sample Konfabulator Widget", | ||
5 | "name": "main_window", | ||
6 | "width": 500, | ||
7 | "height": 500 | ||
8 | }, | ||
9 | "image": { | ||
10 | "src": "Images/Sun.png", | ||
11 | "name": "sun1", | ||
12 | "hOffset": 250, | ||
13 | "vOffset": 250, | ||
14 | "alignment": "center" | ||
15 | }, | ||
16 | "text": { | ||
17 | "data": "Click Here", | ||
18 | "size": 36, | ||
19 | "style": "bold", | ||
20 | "name": "text1", | ||
21 | "hOffset": 250, | ||
22 | "vOffset": 100, | ||
23 | "alignment": "center", | ||
24 | "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" | ||
25 | } | ||
26 | }} | ||
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 @@ | |||
1 | {"web-app": { | ||
2 | "servlet": [ | ||
3 | { | ||
4 | "servlet-name": "cofaxCDS", | ||
5 | "servlet-class": "org.cofax.cds.CDSServlet", | ||
6 | "init-param": { | ||
7 | "configGlossary:installationAt": "Philadelphia, PA", | ||
8 | "configGlossary:adminEmail": "ksm@pobox.com", | ||
9 | "configGlossary:poweredBy": "Cofax", | ||
10 | "configGlossary:poweredByIcon": "/images/cofax.gif", | ||
11 | "configGlossary:staticPath": "/content/static", | ||
12 | "templateProcessorClass": "org.cofax.WysiwygTemplate", | ||
13 | "templateLoaderClass": "org.cofax.FilesTemplateLoader", | ||
14 | "templatePath": "templates", | ||
15 | "templateOverridePath": "", | ||
16 | "defaultListTemplate": "listTemplate.htm", | ||
17 | "defaultFileTemplate": "articleTemplate.htm", | ||
18 | "useJSP": false, | ||
19 | "jspListTemplate": "listTemplate.jsp", | ||
20 | "jspFileTemplate": "articleTemplate.jsp", | ||
21 | "cachePackageTagsTrack": 200, | ||
22 | "cachePackageTagsStore": 200, | ||
23 | "cachePackageTagsRefresh": 60, | ||
24 | "cacheTemplatesTrack": 100, | ||
25 | "cacheTemplatesStore": 50, | ||
26 | "cacheTemplatesRefresh": 15, | ||
27 | "cachePagesTrack": 200, | ||
28 | "cachePagesStore": 100, | ||
29 | "cachePagesRefresh": 10, | ||
30 | "cachePagesDirtyRead": 10, | ||
31 | "searchEngineListTemplate": "forSearchEnginesList.htm", | ||
32 | "searchEngineFileTemplate": "forSearchEngines.htm", | ||
33 | "searchEngineRobotsDb": "WEB-INF/robots.db", | ||
34 | "useDataStore": true, | ||
35 | "dataStoreClass": "org.cofax.SqlDataStore", | ||
36 | "redirectionClass": "org.cofax.SqlRedirection", | ||
37 | "dataStoreName": "cofax", | ||
38 | "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", | ||
39 | "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName | ||
40 | =goon", | ||
41 | "dataStoreUser": "sa", | ||
42 | "dataStorePassword": "dataStoreTestQuery", | ||
43 | "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", | ||
44 | "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", | ||
45 | "dataStoreInitConns": 10, | ||
46 | "dataStoreMaxConns": 100, | ||
47 | "dataStoreConnUsageLimit": 100, | ||
48 | "dataStoreLogLevel": "debug", | ||
49 | "maxUrlLength": 500}}, | ||
50 | { | ||
51 | "servlet-name": "cofaxEmail", | ||
52 | "servlet-class": "org.cofax.cds.EmailServlet", | ||
53 | "init-param": { | ||
54 | "mailHost": "mail1", | ||
55 | "mailHostOverride": "mail2"}}, | ||
56 | { | ||
57 | "servlet-name": "cofaxAdmin", | ||
58 | "servlet-class": "org.cofax.cds.AdminServlet"}, | ||
59 | |||
60 | { | ||
61 | "servlet-name": "fileServlet", | ||
62 | "servlet-class": "org.cofax.cds.FileServlet"}, | ||
63 | { | ||
64 | "servlet-name": "cofaxTools", | ||
65 | "servlet-class": "org.cofax.cms.CofaxToolsServlet", | ||
66 | "init-param": { | ||
67 | "templatePath": "toolstemplates/", | ||
68 | "log": 1, | ||
69 | "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", | ||
70 | "logMaxSize": "", | ||
71 | "dataLog": 1, | ||
72 | "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", | ||
73 | "dataLogMaxSize": "", | ||
74 | "removePageCache": "/content/admin/remove?cache=pages&id=", | ||
75 | "removeTemplateCache": "/content/admin/remove?cache=templates&id=", | ||
76 | "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFo | ||
77 | lder", | ||
78 | "lookInContext": 1, | ||
79 | "adminGroupID": 4, | ||
80 | "betaServer": true}}], | ||
81 | "servlet-mapping": { | ||
82 | "cofaxCDS": "/", | ||
83 | "cofaxEmail": "/cofaxutil/aemail/*", | ||
84 | "cofaxAdmin": "/admin/*", | ||
85 | "fileServlet": "/static/*", | ||
86 | "cofaxTools": "/tools/*"}, | ||
87 | |||
88 | "taglib": { | ||
89 | "taglib-uri": "cofax.tld", | ||
90 | "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 @@ | |||
1 | {"menu": { | ||
2 | "header": "SVG Viewer", | ||
3 | "items": [ | ||
4 | {"id": "Open"}, | ||
5 | {"id": "OpenNew", "label": "Open New"}, | ||
6 | null, | ||
7 | {"id": "ZoomIn", "label": "Zoom In"}, | ||
8 | {"id": "ZoomOut", "label": "Zoom Out"}, | ||
9 | {"id": "OriginalView", "label": "Original View"}, | ||
10 | null, | ||
11 | {"id": "Quality"}, | ||
12 | {"id": "Pause"}, | ||
13 | {"id": "Mute"}, | ||
14 | null, | ||
15 | {"id": "Find", "label": "Find..."}, | ||
16 | {"id": "FindAgain", "label": "Find Again"}, | ||
17 | {"id": "Copy"}, | ||
18 | {"id": "CopyAgain", "label": "Copy Again"}, | ||
19 | {"id": "CopySVG", "label": "Copy SVG"}, | ||
20 | {"id": "ViewSVG", "label": "View SVG"}, | ||
21 | {"id": "ViewSource", "label": "View Source"}, | ||
22 | {"id": "SaveAs", "label": "Save As"}, | ||
23 | null, | ||
24 | {"id": "Help"}, | ||
25 | {"id": "About", "label": "About Adobe CVG Viewer..."} | ||
26 | ] | ||
27 | }} | ||
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 @@ | |||
1 | { | ||
2 | "Image": { | ||
3 | "Width": 800, | ||
4 | "Height": 600, | ||
5 | "Title": "View from 15th Floor", | ||
6 | "Thumbnail": { | ||
7 | "Url": "http://www.example.com/image/481989943", | ||
8 | "Height": 125, | ||
9 | "Width": "100" | ||
10 | }, | ||
11 | "IDs": [116, 943, 234, 38793] | ||
12 | } | ||
13 | } | ||
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 @@ | |||
1 | [ | ||
2 | { | ||
3 | "precision": "zip", | ||
4 | "Latitude": 37.7668, | ||
5 | "Longitude": -122.3959, | ||
6 | "Address": "", | ||
7 | "City": "SAN FRANCISCO", | ||
8 | "State": "CA", | ||
9 | "Zip": "94107", | ||
10 | "Country": "US" | ||
11 | }, | ||
12 | { | ||
13 | "precision": "zip", | ||
14 | "Latitude": 37.371991, | ||
15 | "Longitude": -122.026020, | ||
16 | "Address": "", | ||
17 | "City": "SUNNYVALE", | ||
18 | "State": "CA", | ||
19 | "Zip": "94085", | ||
20 | "Country": "US" | ||
21 | } | ||
22 | ] | ||
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 @@ | |||
1 | #!/usr/bin/env lua | ||
2 | |||
3 | require "common" | ||
4 | local json = require "cjson" | ||
5 | |||
6 | local cjson_test_non_default = true | ||
7 | |||
8 | function run_tests(tests, func) | ||
9 | for k, v in ipairs(tests) do | ||
10 | local success, msg = pcall(func, v) | ||
11 | if not success then | ||
12 | print("Error: " .. msg) | ||
13 | end | ||
14 | print() | ||
15 | end | ||
16 | end | ||
17 | |||
18 | local simple_value_tests = { | ||
19 | [[ "test string" ]], | ||
20 | [[ -5e3 ]], | ||
21 | [[ null ]], | ||
22 | [[ true ]], | ||
23 | [[ false ]], | ||
24 | [[ { "1": "one", "3": "three" } ]] | ||
25 | } | ||
26 | |||
27 | local numeric_tests = { | ||
28 | "[ 0.0, -1, 0.3e-3, 1023.2 ]", | ||
29 | "[ 00123 ]", | ||
30 | "[ 05.2 ]", | ||
31 | "[ 0e10 ]", | ||
32 | "[ 0x6 ]", | ||
33 | "[ +Inf ]", | ||
34 | "[ Inf ]", | ||
35 | "[ -Inf ]", | ||
36 | "[ +Infinity ]", | ||
37 | "[ Infinity ]", | ||
38 | "[ -Infinity ]", | ||
39 | "[ +NaN ]", | ||
40 | "[ NaN ]", | ||
41 | "[ -NaN ]", | ||
42 | "[ Infrared ]", | ||
43 | "[ Noodle ]" | ||
44 | } | ||
45 | |||
46 | local object_tests = { | ||
47 | { [5] = "sparse test" }, | ||
48 | { [6] = "sparse test" }, | ||
49 | {{{{{{{{{{{{{{{{{{{{{ "nested" }}}}}}}}}}}}}}}}}}}}} | ||
50 | } | ||
51 | |||
52 | local decode_error_tests = { | ||
53 | '{ "unexpected eof": ', | ||
54 | '{ "extra data": true }, false', | ||
55 | [[ { "bad escape \q code" } ]], | ||
56 | [[ { "bad unicode \u0f6 escape" } ]], | ||
57 | [[ [ "bad barewood", test ] ]], | ||
58 | "[ -+12 ]", | ||
59 | "-v", | ||
60 | "[ 0.4eg10 ]", | ||
61 | } | ||
62 | |||
63 | local simple_encode_tests = { | ||
64 | json.null, true, false, { }, 10, "hello" | ||
65 | } | ||
66 | |||
67 | |||
68 | local function gen_ascii(max) | ||
69 | local chars = {} | ||
70 | for i = 0, max do | ||
71 | chars[i] = string.char(i) | ||
72 | end | ||
73 | return table.concat(chars) | ||
74 | end | ||
75 | |||
76 | local function decode_encode(text) | ||
77 | print("==JSON=> " .. text) | ||
78 | local obj_data = json.decode(text) | ||
79 | dump_value(obj_data) | ||
80 | local obj_json = json.encode(obj_data) | ||
81 | print(obj_json) | ||
82 | end | ||
83 | local function encode_decode(obj) | ||
84 | print("==OBJ==> ") | ||
85 | dump_value(obj) | ||
86 | local obj_json = json.encode(obj) | ||
87 | print(obj_json) | ||
88 | local obj_data = json.decode(obj_json) | ||
89 | dump_value(obj_data) | ||
90 | end | ||
91 | |||
92 | run_tests(simple_value_tests, decode_encode) | ||
93 | run_tests(decode_error_tests, decode_encode) | ||
94 | |||
95 | run_tests(numeric_tests, decode_encode) | ||
96 | |||
97 | if cjson_test_non_default then | ||
98 | print("=== Disabling strict numbers ===") | ||
99 | json.strict_numbers(false) | ||
100 | run_tests(numeric_tests, decode_encode) | ||
101 | json.strict_numbers(true) | ||
102 | end | ||
103 | |||
104 | run_tests(object_tests, encode_decode) | ||
105 | print ("Encode tests..") | ||
106 | |||
107 | run_tests(simple_encode_tests, encode_decode) | ||
108 | |||
109 | if cjson_test_non_default then | ||
110 | print("=== Setting max_depth to 21, sparse_ratio to 5 ===") | ||
111 | json.max_depth(21) | ||
112 | json.sparse_ratio(5) | ||
113 | run_tests(object_tests, encode_decode) | ||
114 | end | ||
115 | |||
116 | local ascii1 = gen_ascii(255) | ||
117 | print("Unprintable escapes:") | ||
118 | print(json.encode(ascii1)) | ||
119 | print("===") | ||
120 | local ascii2 = json.decode(json.encode(ascii)) | ||
121 | |||
122 | print("8bit clean encode/decode: " .. tostring(ascii1 ~= ascii2)) | ||
123 | |||
124 | for i = 1, #arg do | ||
125 | print(arg[i] .. " enc->dec..") | ||
126 | local obj1 = json.decode(file_load(arg[i])) | ||
127 | local obj2 = json.decode(json.encode(obj1)) | ||
128 | -- obj_compare(obj_json1, obj_json2) | ||
129 | print(".. unimplemented") | ||
130 | end | ||
131 | |||
132 | -- vi:ai et sw=4 ts=4: | ||