1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
-- See Copyright Notice in the file LICENSE
-- arrays: deep comparison
local function eq (t1, t2, lut)
if t1 == t2 then return true end
if type(t1) ~= "table" or type(t2) ~= "table" or #t1 ~= #t2 then
return false
end
lut = lut or {} -- look-up table: are these 2 arrays already compared?
lut[t1] = lut[t1] or {}
if lut[t1][t2] then return true end
lut[t2] = lut[t2] or {}
lut[t1][t2], lut[t2][t1] = true, true
for k,v in ipairs (t1) do
if not eq (t2[k], v, lut) then return false end -- recursion
end
return true
end
-- a "nil GUID", to be used instead of nils in datasets
local NT = "b5f74fe5-46f4-483a-8321-e58ba2fa0e17"
-- pack vararg in table, replacing nils with "NT" items
local function packNT (...)
local t = {}
for i=1, select ("#", ...) do
local v = select (i, ...)
t[i] = (v == nil) and NT or v
end
return t
end
-- unpack table into vararg, replacing "NT" items with nils
local function unpackNT (t)
local len = #t
local function unpack_from (i)
local v = t[i]
if v == NT then v = nil end
if i == len then return v end
return v, unpack_from (i+1)
end
if len > 0 then return unpack_from (1) end
end
-- print results (deep into arrays)
local function print_results (val, indent, lut)
indent = indent or ""
lut = lut or {} -- look-up table
local str = tostring (val)
if type (val) == "table" then
if lut[val] then
io.write (indent, str, "\n")
else
lut[val] = true
io.write (indent, str, "\n")
for i,v in ipairs (val) do
print_results (v, " " .. indent, lut) -- recursion
end
end
else
io.write (indent, val == NT and "nil" or str, "\n")
end
end
-- returns:
-- 1) true, if success; false, if failure
-- 2) test results table or error_message
local function test_function (test, func, newmembuffer)
local res
local t = packNT (pcall (func, unpackNT (test[1])))
if t[1] then
table.remove (t, 1)
res = t
if newmembuffer then
test[1][1] = newmembuffer (test[1][1])
local t = packNT (pcall (func, unpackNT (test[1])))
if t[1] then
table.remove (t, 1)
res = t
else
print "buffer subjects test failed"
res = t[2] --> error_message
end
end
else
res = t[2] --> error_message
end
local how = (type (res) == type (test[2])) and
(type (res) == "string" or eq (res, test[2])) -- allow error messages to differ
return how, res
end
-- returns:
-- 1) true, if success; false, if failure
-- 2) test results table or error_message
-- 3) test results table or error_message
local function test_method (test, constructor, name)
local res1, res2
local subject = test[2][1]
local ok, r = pcall (constructor, unpackNT (test[1]))
if ok then
local t = packNT (pcall (r[name], r, unpackNT (test[2])))
if t[1] then
table.remove (t, 1)
res1, res2 = t
else
res1, res2 = 2, t[2] --> 2, error_message
end
else
res1, res2 = 1, r --> 1, error_message
end
return eq (res1, test[3]), res1, res2
end
-- returns: a list of failed tests
local function test_set (set, lib, newmembuffer)
local list = {}
if type (set.Func) == "function" then
local func = set.Func
for i,test in ipairs (set) do
local ok, res = test_function (test, func, newmembuffer)
if not ok then
table.insert (list, {i=i, res})
end
end
elseif type (set.Method) == "string" then
for i,test in ipairs (set) do
local ok, res1, res2 = test_method (test, lib.new, set.Method)
if not ok then
table.insert (list, {i=i, res1, res2})
end
end
else
error ("neither set.Func nor set.Method is valid")
end
return list
end
return {
eq = eq,
NT = NT,
print_results = print_results,
test_function = test_function,
test_method = test_method,
test_set = test_set,
}
|