| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- #!/usr/bin/env lua
- -- CJSON tests
- --
- -- Mark Pulford <[email protected]>
- --
- -- Note: The output of this script is easier to read with "less -S"
- require "common"
- local json = require "cjson"
- local function gen_ascii()
- local chars = {}
- for i = 0, 255 do chars[i + 1] = string.char(i) end
- return table.concat(chars)
- end
- -- Generate every UTF-16 codepoint, including supplementary codes
- local function gen_utf16_escaped()
- -- Create raw table escapes
- local utf16_escaped = {}
- local count = 0
- local function append_escape(code)
- local esc = string.format('\\u%04X', code)
- table.insert(utf16_escaped, esc)
- end
- table.insert(utf16_escaped, '"')
- for i = 0, 0xD7FF do
- append_escape(i)
- end
- -- Skip 0xD800 - 0xDFFF since they are used to encode supplementary
- -- codepoints
- for i = 0xE000, 0xFFFF do
- append_escape(i)
- end
- -- Append surrogate pair for each supplementary codepoint
- for high = 0xD800, 0xDBFF do
- for low = 0xDC00, 0xDFFF do
- append_escape(high)
- append_escape(low)
- end
- end
- table.insert(utf16_escaped, '"')
- return table.concat(utf16_escaped)
- end
- function test_decode_cycle(filename)
- local obj1 = json.decode(file_load(filename))
- local obj2 = json.decode(json.encode(obj1))
- return compare_values(obj1, obj2)
- end
- local Inf = math.huge;
- local NaN = math.huge * 0;
- local octets_raw = gen_ascii()
- local octets_escaped = file_load("octets-escaped.dat")
- local utf8_loaded, utf8_raw = pcall(file_load, "utf8.dat")
- if not utf8_loaded then
- utf8_raw = "Failed to load utf8.dat"
- end
- local utf16_escaped = gen_utf16_escaped()
- local nested5 = {{{{{ "nested" }}}}}
- local table_cycle = {}
- local table_cycle2 = { table_cycle }
- table_cycle[1] = table_cycle2
- local decode_simple_tests = {
- { json.decode, { '"test string"' }, true, { "test string" } },
- { json.decode, { '-5e3' }, true, { -5000 } },
- { json.decode, { 'null' }, true, { json.null } },
- { json.decode, { 'true' }, true, { true } },
- { json.decode, { 'false' }, true, { false } },
- { json.decode, { '{ "1": "one", "3": "three" }' },
- true, { { ["1"] = "one", ["3"] = "three" } } },
- { json.decode, { '[ "one", null, "three" ]' },
- true, { { "one", json.null, "three" } } }
- }
- local encode_simple_tests = {
- { json.encode, { json.null }, true, { 'null' } },
- { json.encode, { true }, true, { 'true' } },
- { json.encode, { false }, true, { 'false' } },
- { json.encode, { { } }, true, { '{}' } },
- { json.encode, { 10 }, true, { '10' } },
- { json.encode, { NaN },
- false, { "Cannot serialise number: must not be NaN or Inf" } },
- { json.encode, { Inf },
- false, { "Cannot serialise number: must not be NaN or Inf" } },
- { json.encode, { "hello" }, true, { '"hello"' } },
- }
- local decode_numeric_tests = {
- { json.decode, { '[ 0.0, -1, 0.3e-3, 1023.2 ]' },
- true, { { 0.0, -1, 0.0003, 1023.2 } } },
- { json.decode, { '00123' }, true, { 123 } },
- { json.decode, { '05.2' }, true, { 5.2 } },
- { json.decode, { '0e10' }, true, { 0 } },
- { json.decode, { '0x6' }, true, { 6 } },
- { json.decode, { '[ +Inf, Inf, -Inf ]' }, true, { { Inf, Inf, -Inf } } },
- { json.decode, { '[ +Infinity, Infinity, -Infinity ]' },
- true, { { Inf, Inf, -Inf } } },
- { json.decode, { '[ +NaN, NaN, -NaN ]' }, true, { { NaN, NaN, NaN } } },
- { json.decode, { 'Infrared' },
- false, { "Expected the end but found invalid token at character 4" } },
- { json.decode, { 'Noodle' },
- false, { "Expected value but found invalid token at character 1" } },
- }
- local encode_table_tests = {
- function()
- cjson.encode_sparse_array(true, 2, 3)
- cjson.encode_max_depth(5)
- return "Setting sparse array (true, 2, 3) / max depth (5)"
- end,
- { json.encode, { { [3] = "sparse test" } },
- true, { '[null,null,"sparse test"]' } },
- { json.encode, { { [1] = "one", [4] = "sparse test" } },
- true, { '["one",null,null,"sparse test"]' } },
- { json.encode, { { [1] = "one", [5] = "sparse test" } },
- true, { '{"1":"one","5":"sparse test"}' } },
- { json.encode, { { ["2"] = "numeric string key test" } },
- true, { '{"2":"numeric string key test"}' } },
- { json.encode, { nested5 }, true, { '[[[[["nested"]]]]]' } },
- { json.encode, { { nested5 } },
- false, { "Cannot serialise, excessive nesting (6)" } },
- { json.encode, { table_cycle },
- false, { "Cannot serialise, excessive nesting (6)" } }
- }
- local encode_error_tests = {
- { json.encode, { { [false] = "wrong" } },
- false, { "Cannot serialise boolean: table key must be a number or string" } },
- { json.encode, { function () end },
- false, { "Cannot serialise function: type not supported" } },
- function ()
- json.refuse_invalid_numbers("encode")
- return 'Setting refuse_invalid_numbers("encode")'
- end,
- { json.encode, { NaN },
- false, { "Cannot serialise number: must not be NaN or Inf" } },
- { json.encode, { Inf },
- false, { "Cannot serialise number: must not be NaN or Inf" } },
- function ()
- json.refuse_invalid_numbers(false)
- return 'Setting refuse_invalid_numbers(false).'
- end,
- function ()
- print('NOTE: receiving "-nan" in the following test is ok..')
- return
- end,
- { json.encode, { NaN }, true, { "nan" } },
- { json.encode, { Inf }, true, { "inf" } },
- function ()
- json.refuse_invalid_numbers("encode")
- return 'Setting refuse_invalid_numbers("encode")'
- end,
- }
- local json_nested = string.rep("[", 100000) .. string.rep("]", 100000)
- local decode_error_tests = {
- { json.decode, { '\0"\0"' },
- false, { "JSON parser does not support UTF-16 or UTF-32" } },
- { json.decode, { '"\0"\0' },
- false, { "JSON parser does not support UTF-16 or UTF-32" } },
- { json.decode, { '{ "unexpected eof": ' },
- false, { "Expected value but found T_END at character 21" } },
- { json.decode, { '{ "extra data": true }, false' },
- false, { "Expected the end but found T_COMMA at character 23" } },
- { json.decode, { ' { "bad escape \\q code" } ' },
- false, { "Expected object key string but found invalid escape code at character 16" } },
- { json.decode, { ' { "bad unicode \\u0f6 escape" } ' },
- false, { "Expected object key string but found invalid unicode escape code at character 17" } },
- { json.decode, { ' [ "bad barewood", test ] ' },
- false, { "Expected value but found invalid token at character 20" } },
- { json.decode, { '[ -+12 ]' },
- false, { "Expected value but found invalid number at character 3" } },
- { json.decode, { '-v' },
- false, { "Expected value but found invalid number at character 1" } },
- { json.decode, { '[ 0.4eg10 ]' },
- false, { "Expected comma or array end but found invalid token at character 6" } },
- { json.decode, { json_nested },
- false, { "Too many nested data structures" } }
- }
- local escape_tests = {
- -- Test 8bit clean
- { json.encode, { octets_raw }, true, { octets_escaped } },
- { json.decode, { octets_escaped }, true, { octets_raw } },
- -- Ensure high bits are removed from surrogate codes
- { json.decode, { '"\\uF800"' }, true, { "\239\160\128" } },
- -- Test inverted surrogate pairs
- { json.decode, { '"\\uDB00\\uD800"' },
- false, { "Expected value but found invalid unicode escape code at character 2" } },
- -- Test 2x high surrogate code units
- { json.decode, { '"\\uDB00\\uDB00"' },
- false, { "Expected value but found invalid unicode escape code at character 2" } },
- -- Test invalid 2nd escape
- { json.decode, { '"\\uDB00\\"' },
- false, { "Expected value but found invalid unicode escape code at character 2" } },
- { json.decode, { '"\\uDB00\\uD"' },
- false, { "Expected value but found invalid unicode escape code at character 2" } },
- -- Test decoding of all UTF-16 escapes
- { json.decode, { utf16_escaped }, true, { utf8_raw } }
- }
- print(string.format("Testing CJSON v%s\n", cjson.version))
- run_test_group("decode simple value", decode_simple_tests)
- run_test_group("encode simple value", encode_simple_tests)
- run_test_group("decode numeric", decode_numeric_tests)
- -- INCLUDE:
- -- - Sparse array exception..
- -- - ..
- -- cjson.encode_sparse_array(true, 2, 3)
- run_test_group("encode table", encode_table_tests)
- run_test_group("decode error", decode_error_tests)
- run_test_group("encode error", encode_error_tests)
- run_test_group("escape", escape_tests)
- cjson.refuse_invalid_numbers(false)
- cjson.encode_max_depth(20)
- for i = 1, #arg do
- run_test("decode cycle " .. arg[i], test_decode_cycle, { arg[i] },
- true, { true })
- end
- -- vi:ai et sw=4 ts=4:
|