add tests, move expect.lua

I moved expect.lua from library/lua/test/ to library/lua/internal since
luacov is configured to ignore any file with /test/ in its path
develop
myk002 2021-04-03 13:37:11 -07:00
parent 757dbeb238
commit 5af1b627cb
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
4 changed files with 141 additions and 85 deletions

@ -1,7 +1,7 @@
-- DFHack developer test harness
--@ module = true
local expect = require 'test.expect'
local expect = require 'internal.expect'
local json = require 'json'
local script = require 'gui.script'
local utils = require 'utils'

@ -5,7 +5,7 @@
-- these functions directly will not work as expected.
local expect = mkmodule('test.expect')
local expect = mkmodule('internal.expect')
function expect.true_(value, comment)
return not not value, comment, 'expected true, got ' .. tostring(value)
@ -101,20 +101,8 @@ function expect.table_eq(a, b, comment)
('key %s: "%s" ~= "%s"'):format(keystr, diff[1], diff[2])
end
function expect.error(func, comment)
local ok = pcall(func)
if ok then
return false, comment, 'no error raised by function call'
else
return true
end
end
local function matches(obj, matcher)
if not matcher then return false end
if type(matcher) == 'boolean' then
return true
elseif type(matcher) == 'string' then
if type(matcher) == 'string' then
return tostring(obj):match(matcher)
elseif type(matcher) == 'function' then
return matcher(obj)
@ -128,7 +116,6 @@ end
-- matcher can be:
-- a string, interpreted as a lua pattern that matches the error message
-- a function that takes an err object and returns a boolean (true means match)
-- the literal value true, which matches any thrown error
function expect.error_match(matcher, func, comment)
local ok, err = pcall(func)
if ok then
@ -139,10 +126,14 @@ function expect.error_match(matcher, func, comment)
if type(matcher) == 'string' then
matcher_str = (': "%s"'):format(matcher)
end
return false,
return false, comment,
('error "%s" did not satisfy matcher%s'):format(err, matcher_str)
end
function expect.error(func, comment)
return expect.error_match('.*', func, comment)
end
-- matches error messages output from dfhack.printerr() when the specified
-- callback is run. the check passes if all printerr messages are matched by
-- specified matchers and no matchers remain unmatched.
@ -151,24 +142,18 @@ end
-- a string, interpreted as a lua pattern that matches a message
-- a function that takes the string message and returns a boolean (true means
-- match)
-- the literal value true, which matches any message
-- the literal value false, nil, or an empty table, which match the absence of
-- printerr messages
-- a populated table that can be used to match multiple messages (explained
-- in more detail below)
--
-- if matcher is a table, it can contain:
-- a list of strings, literal true values, and/or functions which will be
-- matched in order
-- a map of strings, literal true values, and/or functions to positive
-- integers, which will be matched (in any order) the number of times
-- specified
-- a list of strings and/or functions which will be matched in order
-- a map of strings and/or functions to positive integers, which will be
-- matched (in any order) the number of times specified
--
-- when this function attempts to match a message, it will first try the next
-- matcher in the list (that is, the next numeric key). if that matcher doesn't
-- exist or doesn't match, it will try all string and function keys whose values
-- are numeric and > 0. if none of those match, it will check for a key equal to
-- true with a value > 0.
-- are numeric and > 0.
--
-- if a mapped matcher is matched, it will have its value decremented by 1.
function expect.printerr_match(matcher, func, comment)
@ -178,25 +163,17 @@ function expect.printerr_match(matcher, func, comment)
dfhack.with_finalize(
function() dfhack.printerr = saved_printerr end,
func)
if not matcher then
local num_messages = #messages
if num_messages == 0 then return true end
return false, comment, ('expected 0 calls to dfhack.printerr but got' ..
' %d'):format(num_messages)
end
if type(matcher) ~= 'table' then matcher = {matcher} end
local true_count = matcher[true] or 0
matcher[true] = nil
for _,msg in ipairs(messages) do
local m = matcher[1]
if matches(msg, m) then
while messages[1] do
local msg = messages[1]
if matches(msg, matcher[1]) then
table.remove(matcher, 1)
goto continue
end
for k,v in pairs(matcher) do
if type(v) == 'number' and v > 0 and matches(msg, k) then
local remaining = v - 1
if v == 0 then
if remaining == 0 then
matcher[k] = nil
else
matcher[k] = remaining
@ -204,27 +181,34 @@ function expect.printerr_match(matcher, func, comment)
goto continue
end
end
if true_count > 0 then
true_count = true_count - 1
goto continue
end
return false, comment, ('unmatched printerr message: "%s"'):format(msg)
break -- failed to match message
::continue::
table.remove(messages, 1)
end
local errmsgs, unmatched_messages, extra_matchers = {}, {}, {}
for _,msg in ipairs(messages) do
table.insert(unmatched_messages, ('"%s"'):format(msg))
end
if #unmatched_messages > 0 then
table.insert(errmsgs,
('unmatched dfhack.printerr() messages: %s'):format(
table.concat(unmatched_messages, ', ')))
end
local extra_matchers = {}
for k,v in ipairs(matcher) do
table.insert(extra_matchers, ('"%s"'):format(v))
table.insert(extra_matchers, ('"%s"'):format(tostring(v)))
matcher[k] = nil
end
for k,v in pairs(matcher) do
table.insert(extra_matchers, ('"%s"=%d'):format(k, v))
end
if true_count > 0 then
table.insert(extra_matchers, ('true=%d'):format(true_count))
table.insert(extra_matchers,
('"%s"=%s'):format(tostring(k), tostring(v)))
end
if #extra_matchers > 0 then
return false, comment, ('unmatched or invalid matchers: %s'):format(
table.concat(extra_matchers, ', '))
table.insert(errmsgs,
('unmatched or invalid matchers: %s'):format(
table.concat(extra_matchers, ', ')))
end
if #errmsgs > 0 then
return false, comment, table.concat(errmsgs, '; ')
end
return true
end

@ -0,0 +1,105 @@
local expect_raw = require('internal.expect')
function test.table_eq()
expect.true_(expect_raw.table_eq({}, {}))
expect.true_(expect_raw.table_eq({'a'}, {'a'}))
expect.true_(expect_raw.table_eq({{'a', k='val'}, 'b'},
{{'a', k='val'}, 'b'}))
expect.false_(expect_raw.table_eq(nil, nil)) -- operands must be non-nil
expect.false_(expect_raw.table_eq({}, nil))
expect.false_(expect_raw.table_eq(nil, {}))
expect.false_(expect_raw.table_eq({}, {''}))
expect.false_(expect_raw.table_eq({''}, {}))
expect.false_(expect_raw.table_eq({'a', {}}, {'a'}))
expect.false_(expect_raw.table_eq({{'a', k='val1'}, 'b'},
{{'a', k='val2'}, 'b'}))
local tab = {a='a', b='b'}
expect.true_(expect_raw.table_eq(tab, tab))
expect.true_(expect_raw.table_eq({tab}, {tab}))
local tab1, tab2 = {'a'}, {'a'}
tab1.self, tab2.self = tab1, tab2
expect.true_(expect_raw.table_eq(tab1, tab2))
tab1.other, tab2.other = tab2, tab1
expect.true_(expect_raw.table_eq(tab1, tab2))
local tabA, tabB, tabC, tabD = {k='a'}, {k='a'}, {k='a'}, {k='a'}
tabA.next, tabB.next, tabC.next, tabD.next = tabB, tabC, tabD, tabA
expect.true_(expect_raw.table_eq(tabA, tabB))
end
function test.error_match()
expect.true_(expect_raw.error_match('err', function() error('err0r') end))
expect.false_(expect_raw.error_match('err', function() end))
expect.false_(expect_raw.error_match('00', function() error('err0r') end))
expect.true_(expect_raw.error_match(
function() return true end, function() error('err0r') end))
expect.false_(expect_raw.error_match(
function() return false end, function() error('err0r') end))
end
function test.error()
expect.true_(expect_raw.error(function() error('err0r') end))
expect.true_(expect_raw.error(function() qerror('err0r') end))
expect.false_(expect_raw.error(function() end))
end
function test.printerr_match_printerr_restored()
local prev_printerr = dfhack.printerr
expect_raw.printerr_match('.*', function() dfhack.printerr('a') end)
expect.eq(prev_printerr, dfhack.printerr)
end
function test.printerr_match()
local noprint = function() end
local oneprint = function()
dfhack.printerr('a')
end
local twoprint = function()
dfhack.printerr('a')
dfhack.printerr('b')
end
local threeprint = function()
dfhack.printerr('a')
dfhack.printerr('b')
dfhack.printerr('c')
end
local multiprint = function()
dfhack.printerr('a')
dfhack.printerr('b')
dfhack.printerr('a')
end
expect.true_(expect_raw.printerr_match(nil, noprint))
expect.true_(expect_raw.printerr_match({}, noprint))
expect.false_(expect_raw.printerr_match(nil, oneprint))
expect.false_(expect_raw.printerr_match({}, oneprint))
expect.true_(expect_raw.printerr_match('a', oneprint))
expect.true_(expect_raw.printerr_match({[1]='a'}, oneprint))
expect.true_(expect_raw.printerr_match({a=1}, oneprint))
expect.true_(expect_raw.printerr_match('.', oneprint))
expect.true_(expect_raw.printerr_match({['.']=1}, oneprint))
expect.true_(expect_raw.printerr_match('.*', oneprint))
expect.true_(expect_raw.printerr_match({['.*']=1}, oneprint))
expect.false_(expect_raw.printerr_match('b', oneprint))
expect.false_(expect_raw.printerr_match({b=1}, oneprint))
expect.false_(expect_raw.printerr_match({a=1,b=1}, oneprint))
expect.true_(expect_raw.printerr_match({'a','b'}, twoprint))
expect.true_(expect_raw.printerr_match({a=1,b=1}, twoprint))
expect.false_(expect_raw.printerr_match({'b','a'}, twoprint))
expect.false_(expect_raw.printerr_match({a=1}, twoprint))
expect.false_(expect_raw.printerr_match({b=1}, twoprint))
expect.false_(expect_raw.printerr_match({a=1,b=2}, twoprint))
expect.false_(expect_raw.printerr_match({a=1,b=1,c=1}, twoprint))
expect.true_(expect_raw.printerr_match({a=1,b=1,c=1}, threeprint))
expect.true_(expect_raw.printerr_match({a=2,b=1}, multiprint))
expect.false_(expect_raw.printerr_match({a=1,b=1}, multiprint))
end

@ -1,36 +1,3 @@
local expect_raw = require('test.expect')
function test.internal_in_test()
expect.true_(dfhack.internal.IN_TEST)
end
function test.table_eq()
expect.true_(expect_raw.table_eq({}, {}))
expect.true_(expect_raw.table_eq({'a'}, {'a'}))
expect.true_(expect_raw.table_eq({{'a', k='val'}, 'b'},
{{'a', k='val'}, 'b'}))
expect.false_(expect_raw.table_eq(nil, nil)) -- operands must be non-nil
expect.false_(expect_raw.table_eq({}, nil))
expect.false_(expect_raw.table_eq(nil, {}))
expect.false_(expect_raw.table_eq({}, {''}))
expect.false_(expect_raw.table_eq({''}, {}))
expect.false_(expect_raw.table_eq({'a', {}}, {'a'}))
expect.false_(expect_raw.table_eq({{'a', k='val1'}, 'b'},
{{'a', k='val2'}, 'b'}))
local tab = {a='a', b='b'}
expect.true_(expect_raw.table_eq(tab, tab))
expect.true_(expect_raw.table_eq({tab}, {tab}))
local tab1, tab2 = {'a'}, {'a'}
tab1.self, tab2.self = tab1, tab2
expect.true_(expect_raw.table_eq(tab1, tab2))
tab1.other, tab2.other = tab2, tab1
expect.true_(expect_raw.table_eq(tab1, tab2))
local tabA, tabB, tabC, tabD = {k='a'}, {k='a'}, {k='a'}, {k='a'}
tabA.next, tabB.next, tabC.next, tabD.next = tabB, tabC, tabD, tabA
expect.true_(expect_raw.table_eq(tabA, tabB))
end