tests: adds \u and \x escape encoding/decoding test cases
[luajson.git] / tests / lunit-strings.lua
blobbc8da371a3edcdf4a855faf93954c30ae2d44b81
1 local json = require("json")
2 local lunit = require("lunit")
3 local testutil = require("testutil")
5 local encode = json.encode
6 -- DECODE NOT 'local' due to requirement for testutil to access it
7 decode = json.decode.getDecoder(false)
9 local error = error
11 module("lunit-strings", lunit.testcase, package.seeall)
13 local function assert_table_equal(expect, t)
14 if type(expect) ~= 'table' then
15 return assert_equal(expect, t)
16 end
17 for k,v in pairs(expect) do
18 if type(k) ~= 'string' and type(k) ~= 'number' and type(k) ~= 'boolean' then
19 error("INVALID expected table key")
20 end
21 local found = t[k]
22 if found == nil then
23 fail(tostring(k) .. " not found but expected")
24 end
25 assert_table_equal(v, t[k])
26 end
27 for k,v in pairs(t) do
28 if nil == expect[k] then
29 fail(tostring(k) .. " found but not expected")
30 end
31 end
32 end
34 function setup()
35 -- Ensure that the decoder is reset
36 _G["decode"] = json.decode.getDecoder(false)
37 end
39 function test_encoder_preprocess()
40 local opts = {
41 strings = {
42 preProcess = function(str)
43 return str:gsub("world", "land")
44 end
47 assert_equal([["Hello land"]], json.encode("Hello world", opts))
48 end
50 function test_post_process()
51 local opts = {
52 strings = {
53 postProcess = function(value)
54 -- Test that value processed is after escape handling
55 assert_equal("test\n", value)
56 return "arg"
57 end
60 local decode = json.decode.getDecoder(opts)
61 local ret = decode([["test\n"]])
62 -- Test that returned values are used
63 assert_equal("arg", ret)
64 end
66 function test_strict_quotes()
67 local opts = {
68 strings = {
69 strict_quotes = true
72 assert_error(function()
73 local decoder = json.decode.getDecoder(opts)
74 decoder("'hello'")
75 end)
76 opts.strings.strict_quotes = false
77 assert_equal("hello", json.decode.getDecoder(opts)("'hello'"))
78 -- Quote test
79 assert_equal("he'\"llo'", json.decode.getDecoder(opts)("'he\\'\"llo\\''"))
81 end
83 local utf16_matches = {
84 -- 1-byte
85 { '"\\u0000"', string.char(0x00) },
86 { '"\\u007F"', string.char(0x7F) },
87 -- 2-byte
88 { '"\\u0080"', string.char(0xC2, 0x80) },
89 { '"\\u00A2"', string.char(0xC2, 0xA2) },
90 { '"\\u07FF"', string.char(0xDF, 0xBF) },
91 -- 3-byte
92 { '"\\u0800"', string.char(0xE0, 0xA0, 0x80) },
93 { '"\\u20AC"', string.char(0xE2, 0x82, 0xAC) },
94 { '"\\uFEFF"', string.char(0xEF, 0xBB, 0xBF) },
95 { '"\\uFFFF"', string.char(0xEF, 0xBF, 0xBF) }
98 function test_utf16_decode()
99 for i, v in ipairs(utf16_matches) do
100 -- Test that the default \u decoder outputs UTF8
101 local num = tostring(i) .. ' '
102 assert_equal(num .. v[2], num .. json.decode(v[1]))
106 local BOM = string.char(0xEF, 0xBB, 0xBF)
107 -- BOM skipping tests - here due to relation to UTF8/16
108 local BOM_skip_tests = {
109 { BOM .. '"x"', "x" },
110 { BOM .. '["\\uFFFF",true]', { string.char(0xEF, 0xBF, 0xBF), true } },
111 -- Other uses of unicode spaces
114 function test_bom_skip()
115 for i,v in ipairs(BOM_skip_tests) do
116 assert_table_equal(v[2], json.decode(v[1]))
120 -- Unicode whitespace codepoints gleaned from unicode.org
121 local WHITESPACES = {
122 "\\u0009", -- \t
123 "\\u000A", -- \n
124 "\\u000B", -- \v
125 "\\u000C", -- \f
126 "\\u000D", -- \r
127 "\\u0020", -- space
128 "\\u0085",
129 "\\u00A0",
130 "\\u1680",
131 "\\u180E",
132 "\\u2000",
133 "\\u2001",
134 "\\u2002",
135 "\\u2003",
136 "\\u2004",
137 "\\u2005",
138 "\\u2006",
139 "\\u2007",
140 "\\u2008",
141 "\\u2009",
142 "\\u200A",
143 "\\u200B", -- addition, zero-width space
144 "\\u2028",
145 "\\u2029",
146 "\\u202F",
147 "\\u205F",
148 "\\u3000",
149 "\\uFEFF" -- Zero-width non-breaking space (BOM)
152 local inject_ws_values = {
153 "%WS%true",
154 " %WS%'the%WS blob' %WS%",
155 "%WS%{ key: %WS%\"valueMan\",%WS% key2:%WS%4.4}",
156 "%WS%false%WS%"
158 function test_whitespace_ignore()
159 for _, ws in ipairs(WHITESPACES) do
160 ws = json.decode('"' .. ws .. '"')
161 for _, v in ipairs(inject_ws_values) do
162 v = v:gsub("%%WS%%", ws)
163 assert_true(nil ~= json.decode(v))
168 function test_u_encoding()
169 local encoder = json.encode.getEncoder()
170 local decoder = json.decode.getDecoder()
171 for i = 0, 255 do
172 local char = string.char(i)
173 assert_equal(char, decoder(encoder(char)))
177 function test_x_encoding()
178 local encoder = json.encode.getEncoder({ strings = { xEncode = true } })
179 local decoder = json.decode.getDecoder()
180 for i = 0, 255 do
181 local char = string.char(i)
182 assert_equal(char, decoder(encoder(char)))