99 lines
4.1 KiB
Lua
Executable File
Raw Permalink Blame History

-- we need to test all the different formats, at minimum
-- this means bimPpsuxz for now
-- Copyright <20> 2008 Ben "ToxicFrog" Kelly; see COPYING
-- test cases
-- simple: read and write of each format, seeks, endianness controls
-- complex: naming, tables, repetition, combinations of all of these,
-- nested tables, multi formats per string
-- non-obvious: seek past end of file
-- error handling: seek past start, read past end, invalid widths,
-- non-isomorphic input tables
local c = string.char
local require,math,ipairs,string,tostring,print,os,pairs
= require,math,ipairs,string,tostring,print,os,pairs
module((...))
local struct = require(_NAME:match("^[^%.]+"))
local name = (...):gsub('%.[^%.]+$', '')
local function check_bm(m)
m = m.m
return m[8] and m[7] and m[6] and m[5]
and m[4] and not m[3] and m[2] and not m[1]
end
local tests = {
-- booleans
{ raw = "\0\0\0\0\0\0\0\1"; format = "b8"; val = true; },
{ raw = "\1\0\0\0\0\0\0\0"; format = "(b8)*1"; val = true; },
{ raw = "\0\0\0\0\0\0\0\0"; format = "1*(b8)"; val = false; },
-- signed integers
{ raw = "\254\255\255"; format = "< i3"; val = -2; },
-- unsigned integers
{ raw = "\254\255\255"; format = "< u3"; val = 2^24-2; },
-- bitmasks
{ raw = "\250"; format = "{m:m1}"; test = check_bm; },
-- fixed point
{ raw = "\1\128"; format = "> P8.8"; val = 1.5; },
{ raw = "\2\192"; format = "> p1.1"; val = 2.75; },
-- plain strings
{ raw = "foobar"; format = "s4"; val = "foob"; },
-- counted strings
{ raw = "\006\000\000\000foobar"; format = "< c4"; val = "foobar"; },
-- null terminated strings
{ raw = "foobar\0baz"; format = "z"; val = "foobar"; },
{ raw = "foobar\0baz"; format = "z10"; val = "foobar"; },
-- floats
{ raw = c(0x00, 0x00, 0x00, 0x00); format = "< f4"; val = 0.0; },
{ raw = c(0x3f, 0x80, 0x00, 0x00); format = "> f4"; val = 1.0; },
{ raw = c(0x00, 0x00, 0x80, 0x3f); format = "< f4"; val = 1.0; },
{ raw = c(0x00, 0x00, 0x80, 0xbf); format = "< f4"; val = -1.0; },
{ raw = c(0x00, 0x00, 0x80, 0x7f); format = "< f4"; val = math.huge; },
{ raw = c(0x00, 0x00, 0x80, 0xff); format = "< f4"; val = -math.huge; },
{ raw = c(0x00, 0x00, 0xc0, 0x7f); format = "< f4"; val = 0/0; test = function(v) return v ~= v end },
{ raw = c(0x00, 0x00, 0xc0, 0xff); format = "< f4"; val = 0/0; test = function(v) return v ~= v end },
-- doubles
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); format = "< f8"; val = 0.0; },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f); format = "< f8"; val = 1.0; },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf); format = "< f8"; val = -1.0; },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f); format = "< f8"; val = math.huge; },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff); format = "< f8"; val = -math.huge; },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f); format = "< f8"; val = 0/0; test = function(v) return v ~= v end },
{ raw = c(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff); format = "< f8"; val = 0/0; test = function(v) return v ~= v end },
}
function od(str)
return str:gsub('.', function(c) return string.format("%02X ", c:byte()) end)
end
function check(test)
local val, pass, raw
local fmt = "%7.7s %42.42s%2.2s %17.17s %4.4s %3.3s"
val = struct.unpack(test.format, test.raw)[1]
pass = test.test
and test.test(val)
or val == test.val
print(fmt:format(test.format, od(test.raw), "=>", tostring(val), pass and "PASS" or "FAIL", pass and "" or "!!!"):sub(1,79))
if not pass then return end
raw = struct.pack(test.format, {val})
pass = raw == test.raw
-- if we have a failure, it might be because there are multiple valid on-disk forms
-- for example, a boolean can be any non-zero value, but we always write it back out as 1
-- so, re-read it using the same format and see if it matches
if not pass then
local new_val = struct.unpack(test.format, raw)[1]
pass = test.test and test.test(val) or new_val == test.val
end
print(fmt:format(test.format, od(raw), "<=", tostring(val), pass and "PASS" or "FAIL", pass and "" or " !!!"):sub(1,79))
end
for i,test in ipairs(tests) do
check(test)
end
os.exit(0)