152 lines
3.7 KiB
Lua
152 lines
3.7 KiB
Lua
local json = require("json")
|
|
local lunit = require("lunit")
|
|
local math = require("math")
|
|
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)
|
|
|
|
module("lunit-numbers", lunit.testcase, package.seeall)
|
|
|
|
function setup()
|
|
-- Ensure that the decoder is reset
|
|
_G["decode"] = json.decode.getDecoder(false)
|
|
end
|
|
|
|
local function assert_near(expect, received)
|
|
local pctDiff
|
|
if expect == received then
|
|
pctDiff = 0
|
|
else
|
|
pctDiff = math.abs(1 - expect / received)
|
|
end
|
|
local msg = ("expected '%s' but was '%s' .. '%s'%% apart"):format(expect, received, pctDiff * 100)
|
|
assert(pctDiff < 0.000001, msg)
|
|
end
|
|
local function test_simple(num)
|
|
assert_near(num, decode(tostring(num)))
|
|
end
|
|
local function test_simple_w_encode(num)
|
|
assert_near(num, decode(encode(num)))
|
|
end
|
|
local function test_scientific(num)
|
|
assert_near(num, decode(string.format('%e', num)))
|
|
assert_near(num, decode(string.format('%E', num)))
|
|
end
|
|
local numbers = {
|
|
0, 1, -1, math.pi, -math.pi
|
|
}
|
|
math.randomseed(0xDEADBEEF)
|
|
-- Add sequence of numbers at low/high end of value-set
|
|
for i = -300,300,60 do
|
|
numbers[#numbers + 1] = math.random() * math.pow(10, i)
|
|
numbers[#numbers + 1] = -math.random() * math.pow(10, i)
|
|
end
|
|
|
|
local function get_number_tester(f)
|
|
return function ()
|
|
for _, v in ipairs(numbers) do
|
|
f(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
test_simple_numbers = get_number_tester(test_simple)
|
|
test_simple_numbers_w_encode = get_number_tester(test_simple_w_encode)
|
|
test_simple_numbers_scientific = get_number_tester(test_scientific)
|
|
|
|
function test_infinite_nostrict()
|
|
assert_equal(math.huge, decode("Infinity"))
|
|
assert_equal(math.huge, decode("infinity"))
|
|
assert_equal(-math.huge, decode("-Infinity"))
|
|
assert_equal(-math.huge, decode("-infinity"))
|
|
end
|
|
|
|
function test_nan_nostrict()
|
|
local value = decode("nan")
|
|
assert_true(value ~= value)
|
|
local value = decode("NaN")
|
|
assert_true(value ~= value)
|
|
end
|
|
|
|
function test_expression()
|
|
assert_error(function()
|
|
decode("1 + 2")
|
|
end)
|
|
end
|
|
|
|
-- For strict tests, small concession must be made to allow non-array/objects as root
|
|
local strict = json.util.merge({}, json.decode.strict, {initialObject = false})
|
|
local strictDecoder = json.decode.getDecoder(strict)
|
|
|
|
local numberValue = {hex = true}
|
|
|
|
local hex = {number = numberValue}
|
|
local hexDecoder = json.decode.getDecoder(hex)
|
|
|
|
function test_hex()
|
|
if decode == hexDecoder then -- MUST SKIP FAIL UNTIL BETTER METHOD SETUP
|
|
return
|
|
end
|
|
assert_error(function()
|
|
decode("0x20")
|
|
end)
|
|
end
|
|
|
|
local hexNumbers = {
|
|
0xDEADBEEF,
|
|
0xCAFEBABE,
|
|
0x00000000,
|
|
0xFFFFFFFF,
|
|
0xCE,
|
|
0x01
|
|
}
|
|
|
|
function test_hex_only()
|
|
_G["decode"] = hexDecoder
|
|
for _, v in ipairs(hexNumbers) do
|
|
assert_equal(v, decode(("0x%x"):format(v)))
|
|
assert_equal(v, decode(("0X%X"):format(v)))
|
|
assert_equal(v, decode(("0x%X"):format(v)))
|
|
assert_equal(v, decode(("0X%x"):format(v)))
|
|
end
|
|
end
|
|
|
|
local decimal_hexes = {
|
|
"0x0.1",
|
|
"0x.1",
|
|
"0x0e+1",
|
|
"0x0E-1"
|
|
}
|
|
function test_no_decimal_hex_only()
|
|
for _, str in ipairs(decimal_hexes) do
|
|
assert_error(function()
|
|
hexDecoder(str)
|
|
end)
|
|
end
|
|
end
|
|
|
|
function test_nearly_scientific_hex_only()
|
|
assert_equal(0x00E1, hexDecoder("0x00e1"))
|
|
end
|
|
|
|
local function buildStrictDecoder(f)
|
|
return testutil.buildPatchedDecoder(f, strictDecoder)
|
|
end
|
|
local function buildFailedStrictDecoder(f)
|
|
return testutil.buildFailedPatchedDecoder(f, strictDecoder)
|
|
end
|
|
-- SETUP CHECKS FOR SEQUENCE OF DECODERS
|
|
for k, v in pairs(_M) do
|
|
if k:match("^test_") and not k:match("_gen$") and not k:match("_only$") then
|
|
if k:match("_nostrict") then
|
|
_M[k .. "_strict_gen"] = buildFailedStrictDecoder(v)
|
|
else
|
|
_M[k .. "_strict_gen"] = buildStrictDecoder(v)
|
|
end
|
|
_M[k .. "_hex_gen"] = testutil.buildPatchedDecoder(v, hexDecoder)
|
|
end
|
|
end
|