1 local json
= require("json")
2 local lunit
= require("lunit")
3 local math
= require("math")
4 local testutil
= require("testutil")
5 local string = require("string")
7 local encode
= json
.encode
8 -- DECODE NOT 'local' due to requirement for testutil to access it
9 decode
= json
.decode
.getDecoder(false)
11 module("lunit-numbers", lunit
.testcase
, package
.seeall
)
14 -- Ensure that the decoder is reset
15 _G
["decode"] = json
.decode
.getDecoder(false)
18 local function assert_near(expect
, received
)
20 if expect
== received
then
23 pctDiff
= math
.abs(1 - expect
/ received
)
25 local msg
= ("expected '%s' but was '%s' .. '%s'%% apart"):format(expect
, received
, pctDiff
* 100)
26 assert(pctDiff
< 0.000001, msg
)
28 local function test_simple(num
)
29 assert_near(num
, decode(tostring(num
)))
31 local function test_simple_w_encode(num
)
32 assert_near(num
, decode(encode(num
)))
34 local function test_scientific(num
)
35 assert_near(num
, decode(string.format('%e', num
)))
36 assert_near(num
, decode(string.format('%E', num
)))
39 0, 1, -1, math
.pi
, -math
.pi
41 math
.randomseed(0xDEADBEEF)
42 -- Add sequence of numbers at low/high end of value-set
43 for i
= -300,300,60 do
44 numbers
[#numbers
+ 1] = math
.random() * math
.pow(10, i
)
45 numbers
[#numbers
+ 1] = -math
.random() * math
.pow(10, i
)
48 local function get_number_tester(f
)
50 for _
, v
in ipairs(numbers
) do
56 test_simple_numbers
= get_number_tester(test_simple
)
57 test_simple_numbers_w_encode
= get_number_tester(test_simple_w_encode
)
58 test_simple_numbers_scientific
= get_number_tester(test_scientific
)
60 function test_infinite_nostrict()
61 assert_equal(math
.huge
, decode("Infinity"))
62 assert_equal(math
.huge
, decode("infinity"))
63 assert_equal(-math
.huge
, decode("-Infinity"))
64 assert_equal(-math
.huge
, decode("-infinity"))
67 function test_nan_nostrict()
68 local value
= decode("nan")
69 assert_true(value
~= value
)
70 local value
= decode("NaN")
71 assert_true(value
~= value
)
74 function test_expression()
75 assert_error(function()
80 -- For strict tests, small concession must be made to allow non-array/objects as root
81 local strict
= json
.util
.merge({}, json
.decode
.strict
, {initialObject
= false})
82 local strictDecoder
= json
.decode
.getDecoder(strict
)
84 local numberValue
= {hex
= true}
86 local hex
= {number = numberValue
}
87 local hexDecoder
= json
.decode
.getDecoder(hex
)
90 if decode
== hexDecoder
then -- MUST SKIP FAIL UNTIL BETTER METHOD SETUP
93 assert_error(function()
107 function test_hex_only()
108 _G
["decode"] = hexDecoder
109 for _
, v
in ipairs(hexNumbers
) do
110 assert_equal(v
, decode(("0x%x"):format(v
)))
111 assert_equal(v
, decode(("0X%X"):format(v
)))
112 assert_equal(v
, decode(("0x%X"):format(v
)))
113 assert_equal(v
, decode(("0X%x"):format(v
)))
117 local decimal_hexes
= {
123 function test_no_decimal_hex_only()
124 for _
, str
in ipairs(decimal_hexes
) do
125 assert_error(function()
131 function test_nearly_scientific_hex_only()
132 assert_equal(0x00E1, hexDecoder("0x00e1"))
135 local function buildStrictDecoder(f
)
136 return testutil
.buildPatchedDecoder(f
, strictDecoder
)
138 local function buildFailedStrictDecoder(f
)
139 return testutil
.buildFailedPatchedDecoder(f
, strictDecoder
)
141 -- SETUP CHECKS FOR SEQUENCE OF DECODERS
142 for k
, v
in pairs(_M
) do
143 if k
:match("^test_") and not k
:match("_gen$") and not k
:match("_only$") then
144 if k
:match("_nostrict") then
145 _M
[k
.. "_strict_gen"] = buildFailedStrictDecoder(v
)
147 _M
[k
.. "_strict_gen"] = buildStrictDecoder(v
)
149 _M
[k
.. "_hex_gen"] = testutil
.buildPatchedDecoder(v
, hexDecoder
)