blob: 305df1614f7fda5af33bd9578eabbe26c83e4b15 [file] [log] [blame]
local json = require("json")
local lunit = require("lunit")
local testutil = require("testutil")
local string= require("string")
local encode = json.encode
-- DECODE NOT 'local' due to requirement for testutil to access it
decode = json.decode.getDecoder(false)
local error = error
module("lunit-strings", lunit.testcase, package.seeall)
local function assert_table_equal(expect, t)
if type(expect) ~= 'table' then
return assert_equal(expect, t)
end
for k,v in pairs(expect) do
if type(k) ~= 'string' and type(k) ~= 'number' and type(k) ~= 'boolean' then
error("INVALID expected table key")
end
local found = t[k]
if found == nil then
fail(tostring(k) .. " not found but expected")
end
assert_table_equal(v, t[k])
end
for k,v in pairs(t) do
if nil == expect[k] then
fail(tostring(k) .. " found but not expected")
end
end
end
function setup()
-- Ensure that the decoder is reset
_G["decode"] = json.decode.getDecoder(false)
end
function test_strict_quotes()
local opts = {
strings = {
strict_quotes = true
}
}
assert_error(function()
local decoder = json.decode.getDecoder(opts)
decoder("'hello'")
end)
opts.strings.strict_quotes = false
assert_equal("hello", json.decode.getDecoder(opts)("'hello'"))
-- Quote test
assert_equal("he'\"llo'", json.decode.getDecoder(opts)("'he\\'\"llo\\''"))
end
local utf16_matches = {
-- 1-byte
{ '"\\u0000"', string.char(0x00) },
{ '"\\u007F"', string.char(0x7F) },
-- 2-byte
{ '"\\u0080"', string.char(0xC2, 0x80) },
{ '"\\u00A2"', string.char(0xC2, 0xA2) },
{ '"\\u07FF"', string.char(0xDF, 0xBF) },
-- 3-byte
{ '"\\u0800"', string.char(0xE0, 0xA0, 0x80) },
{ '"\\u20AC"', string.char(0xE2, 0x82, 0xAC) },
{ '"\\uFEFF"', string.char(0xEF, 0xBB, 0xBF) },
{ '"\\uFFFF"', string.char(0xEF, 0xBF, 0xBF) }
}
function test_utf16_decode()
for i, v in ipairs(utf16_matches) do
-- Test that the default \u decoder outputs UTF8
local num = tostring(i) .. ' '
assert_equal(num .. v[2], num .. json.decode(v[1]))
end
end
local BOM = string.char(0xEF, 0xBB, 0xBF)
-- BOM skipping tests - here due to relation to UTF8/16
local BOM_skip_tests = {
{ BOM .. '"x"', "x" },
{ BOM .. '["\\uFFFF",true]', { string.char(0xEF, 0xBF, 0xBF), true } },
-- Other uses of unicode spaces
}
function test_bom_skip()
for i,v in ipairs(BOM_skip_tests) do
assert_table_equal(v[2], json.decode(v[1]))
end
end
-- Unicode whitespace codepoints gleaned from unicode.org
local WHITESPACES = {
"\\u0009", -- \t
"\\u000A", -- \n
"\\u000B", -- \v
"\\u000C", -- \f
"\\u000D", -- \r
"\\u0020", -- space
"\\u0085",
"\\u00A0",
"\\u1680",
"\\u180E",
"\\u2000",
"\\u2001",
"\\u2002",
"\\u2003",
"\\u2004",
"\\u2005",
"\\u2006",
"\\u2007",
"\\u2008",
"\\u2009",
"\\u200A",
"\\u200B", -- addition, zero-width space
"\\u2028",
"\\u2029",
"\\u202F",
"\\u205F",
"\\u3000",
"\\uFEFF" -- Zero-width non-breaking space (BOM)
}
local inject_ws_values = {
"%WS%true",
" %WS%'the%WS blob' %WS%",
"%WS%{ key: %WS%\"valueMan\",%WS% key2:%WS%4.4}",
"%WS%false%WS%"
}
function test_whitespace_ignore()
for _, ws in ipairs(WHITESPACES) do
ws = json.decode('"' .. ws .. '"')
for _, v in ipairs(inject_ws_values) do
v = v:gsub("%%WS%%", ws)
assert_true(nil ~= json.decode(v))
end
end
end
function test_u_encoding()
local encoder = json.encode.getEncoder()
local decoder = json.decode.getDecoder()
for i = 0, 255 do
local char = string.char(i)
assert_equal(char, decoder(encoder(char)))
end
end
function test_x_encoding()
local encoder = json.encode.getEncoder({ strings = { xEncode = true } })
local decoder = json.decode.getDecoder()
for i = 0, 255 do
local char = string.char(i)
assert_equal(char, decoder(encoder(char)))
end
end
function test_strict_decoding()
local encoder = json.encode.getEncoder(json.encode.strict)
local decoder = json.decode.getDecoder(json.decode.strict)
for i = 0, 255 do
local char = string.char(i)
-- Must wrap character in array due to decoder strict-ness
assert_equal(char, decoder(encoder({char}))[1])
end
end