99 lines
4.1 KiB
Lua
Executable File
99 lines
4.1 KiB
Lua
Executable File
-- 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)
|