Files
op-packages/luci-app-substore/tests/util_json_test.lua
T

141 lines
4.7 KiB
Lua

-- util_json_test.lua — JSON 编解码保真与错误上报单元测试
-- 用法:lua5.1 tests/util_json_test.lua
--
-- 覆盖审计表 M13(null / 空对象往返被改写)与 M14(json_decode 永不返回错误串)。
package.path = "./root/usr/share/?.lua;" .. package.path
local util = require("substore.util")
local passed, failed = 0, 0
local function check(name, cond)
if cond then
passed = passed + 1
else
failed = failed + 1
print("FAIL: " .. name)
end
end
local function rt(s) -- 解码再编码,返回编码结果与错误
local v, err = util.json_decode(s)
if err then return nil, err end
return util.json_encode(v)
end
-- ---------- M14:错误必须上报 ----------
do
local _, err = util.json_decode("{")
check("M14 unterminated object reports error", type(err) == "string")
local _, err2 = util.json_decode("[1,2")
check("M14 unterminated array reports error", type(err2) == "string")
local _, err3 = util.json_decode('{"a":}')
check("M14 missing value reports error", type(err3) == "string")
local _, err4 = util.json_decode("[1,]")
check("M14 trailing comma in array rejected", type(err4) == "string")
local _, err5 = util.json_decode('{"a":1,}')
check("M14 trailing comma in object rejected", type(err5) == "string")
-- 合法输入不得被误判
local v, e = util.json_decode('{"a":1}')
check("M14 valid object still parses", type(v) == "table" and v.a == 1 and e == nil)
local arr, e2 = util.json_decode("[1,2,3]")
check("M14 valid array still parses", type(arr) == "table" and #arr == 3 and e2 == nil)
-- 顶层 null 是合法 JSON,必须与「解析失败」区分开
local n, e3 = util.json_decode("null")
check("M14 top-level null is valid, not an error", n == nil and e3 == nil)
end
-- ---------- M14:尾部脏数据必须拒绝 ----------
do
local _, err = util.json_decode("1 2")
check("M14 trailing content after number rejected", type(err) == "string")
local _, err2 = util.json_decode("[1] junk")
check("M14 trailing content after array rejected", type(err2) == "string")
local _, err3 = util.json_decode('{"a":1}{"b":2}')
check("M14 two concatenated objects rejected", type(err3) == "string")
local _, err4 = util.json_decode("1.2.3")
check("M14 malformed number rejected", type(err4) == "string")
-- 尾随空白是合法的
local v, e = util.json_decode("[1] \n\t ")
check("M14 trailing whitespace allowed", type(v) == "table" and v[1] == 1 and e == nil)
end
-- ---------- M13:数组中的 null 往返保持 null ----------
do
local out = rt("[null,1]")
check("M13 null in array round-trips to null", out == "[null,1]")
local out2 = rt("[null,null]")
check("M13 multiple nulls round-trip", out2 == "[null,null]")
local out3 = rt('{"a":[1,null,2]}')
check("M13 nested null in object array round-trips", out3 == '{"a":[1,null,2]}')
-- 编码侧直接喂 null 占位符
local decoded = util.json_decode("[null]")
check("M13 decoded null slot is a table placeholder", type(decoded) == "table" and type(decoded[1]) == "table")
end
-- ---------- M13:空对象往返保持对象 ----------
do
local out = rt('{"tls":{}}')
check("M13 empty object round-trips as object", out == '{"tls":{}}')
local out2 = rt('{"settings":{},"x":1}')
check("M13 empty object among other keys round-trips", out2 == '{"settings":{},"x":1}')
-- 空数组仍须保持数组
local out3 = rt("[]")
check("M13 empty array still round-trips as array", out3 == "[]")
local out4 = rt('{"a":[]}')
check("M13 empty array value round-trips", out4 == '{"a":[]}')
-- 显式常量仍然有效
check("M13 JSON_EMPTY_OBJECT still encodes to {}", util.json_encode(util.JSON_EMPTY_OBJECT) == "{}")
end
-- ---------- 回归:既有行为不得被破坏 ----------
do
local out = rt('{"a":1,"b":"x","c":true,"d":false}')
check("regression object scalars", out ~= nil and out:find('"a":1', 1, true) ~= nil
and out:find('"b":"x"', 1, true) ~= nil and out:find('"c":true', 1, true) ~= nil)
local out2 = rt('[1,2,3]')
check("regression plain array", out2 == "[1,2,3]")
local out3 = rt('"hello"')
check("regression plain string", out3 == '"hello"')
local out4 = rt("42")
check("regression plain number", out4 == "42")
-- 转义序列
local s = util.json_decode('"a\\nb\\tc\\"d"')
check("regression escape sequences", s == 'a\nb\tc"d')
-- unicode 转义
local u = util.json_decode('"\\u4e2d"')
check("regression unicode escape", u == "中")
-- 空对象解码后仍是 table 且可被 pairs 遍历(调用方普遍这么用)
local o = util.json_decode("{}")
local cnt = 0
for _ in pairs(o) do cnt = cnt + 1 end
check("regression decoded empty object iterable", type(o) == "table" and cnt == 0)
end
print(string.format("\n%d passed, %d failed", passed, failed))
os.exit(failed == 0 and 0 or 1)