Add a basic test library and a couple GUI module tests (squashed)

Also modified Core/Console a bit to get this to actually produce output on
Travis (DFHACK_DISABLE_CONSOLE now allows console output, just not input)

Squashed merge from lethosor/tests
develop
lethosor 2018-07-18 14:29:13 -04:00
parent a779b247d4
commit 063602349c
7 changed files with 198 additions and 13 deletions

@ -33,6 +33,7 @@ before_install:
- sh travis/build-lua.sh
- sh travis/download-df.sh
- echo "export DFHACK_HEADLESS=1" >> "$HOME/.dfhackrc"
- echo "export DFHACK_DISABLE_CONSOLE=1" >> "$HOME/.dfhackrc"
script:
- export PATH="$PATH:$HOME/lua53/bin"
- git tag tmp-travis-build
@ -46,17 +47,19 @@ script:
- python travis/script-syntax.py --ext=rb --cmd="ruby -c"
- mkdir build-travis
- cd build-travis
- cmake .. -G Ninja -DCMAKE_C_COMPILER=gcc-$GCC_VERSION -DCMAKE_CXX_COMPILER=g++-$GCC_VERSION -DDFHACK_BUILD_ARCH=64 -DBUILD_DOCS:BOOL=ON -DCMAKE_INSTALL_PREFIX="$DF_FOLDER"
- cmake .. -G Ninja -DCMAKE_C_COMPILER=gcc-$GCC_VERSION -DCMAKE_CXX_COMPILER=g++-$GCC_VERSION -DDFHACK_BUILD_ARCH=64 -DBUILD_DOCS:BOOL=ON -DBUILD_SUPPORTED:BOOL=OFF -DCMAKE_INSTALL_PREFIX="$DF_FOLDER"
- ninja -j3 install
- mv "$DF_FOLDER"/dfhack.init-example "$DF_FOLDER"/dfhack.init
- cd ..
- cp travis/dfhack_travis.init "$DF_FOLDER"/
- python travis/run-tests.py "$DF_FOLDER"
- python travis/check-rpc.py "$DF_FOLDER/dfhack-rpc.txt"
- cat "$DF_FOLDER/stderr.log"
- rm -rf "$DF_FOLDER/hack"
notifications:
email: false
irc:
channels:
- "chat.freenode.net#dfhack"
on_success: change
on_failure: always
# irc:
# channels:
# - "chat.freenode.net#dfhack"
# on_success: change
# on_failure: always

@ -406,6 +406,7 @@ file(WRITE "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" ${DFHACK_SETARCH})
install(FILES "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" DESTINATION "${DFHACK_DATA_DESTINATION}")
install(DIRECTORY dfhack-config/ DESTINATION dfhack-config/default)
install(DIRECTORY test DESTINATION "${DFHACK_DATA_DESTINATION}")
#build the plugins
IF(BUILD_PLUGINS)

@ -1476,6 +1476,10 @@ void fIOthread(void * iodata)
dfhack_version_desc().c_str());
int clueless_counter = 0;
if (getenv("DFHACK_DISABLE_CONSOLE"))
return;
while (true)
{
string command = "";
@ -1705,7 +1709,7 @@ bool Core::Init()
cerr << "Headless mode not supported on Windows" << endl;
#endif
}
if ((is_text_mode && !is_headless) || getenv("DFHACK_DISABLE_CONSOLE"))
if (is_text_mode && !is_headless)
{
con.init(true);
cerr << "Console is not available. Use dfhack-run to send commands.\n";

@ -0,0 +1,25 @@
function test.getCurViewscreen()
local scr = dfhack.gui.getCurViewscreen()
local scr2 = df.global.gview.view
for i = 1, 100 do
if scr2.child then
scr2 = scr2.child
else
break
end
end
expect.eq(scr, scr2)
end
function test.getViewscreenByType()
local scr = dfhack.gui.getCurViewscreen()
local scr2 = dfhack.gui.getViewscreenByType(scr._type)
expect.eq(scr, scr2)
local bad_type = df.viewscreen_titlest
if scr._type == bad_type then
bad_type = df.viewscreen_optionst
end
local scr_bad = dfhack.gui.getViewscreenByType(bad_type)
expect.eq(scr_bad, nil)
end

@ -1,10 +1,157 @@
local args = {...}
local done_command = args[1]
expect = {}
function expect.true_(value)
return not not value
end
function expect.false_(value)
return not value
end
function expect.eq(a, b)
return a == b
end
function expect.ne(a, b)
return a ~= b
end
function expect.error(func, ...)
local ok, ret = pcall(func, ...)
if ok then
return false, 'no error raised by function call'
else
return true
end
end
function build_test_env()
local env = {
test = {},
expect = {},
}
local private = {
checks = 0,
checks_ok = 0,
}
for name, func in pairs(expect) do
env.expect[name] = function(...)
private.checks = private.checks + 1
local ok, msg = func(...)
if ok then
private.checks_ok = private.checks_ok + 1
else
dfhack.printerr('Check failed! ' .. (msg or '(no message)'))
local info = debug.getinfo(2)
dfhack.printerr((' at %s:%d'):format(info.short_src, info.currentline))
print('')
end
end
end
setmetatable(env, {__index = _G})
return env, private
end
function get_test_files()
local files = {}
for _, entry in ipairs(dfhack.filesystem.listdir_recursive(dfhack.getHackPath() .. 'test')) do
if not entry.isdir and not entry.path:match('main.lua') then
table.insert(files, entry.path)
end
end
table.sort(files)
return files
end
function set_test_stage(stage)
local f = io.open('test_stage.txt', 'w')
f:write(stage)
f:close()
end
print('running tests')
function finish_tests(ok)
if ok then
print('Tests finished')
else
dfhack.printerr('Tests failed!')
end
if done_command then
dfhack.run_command(done_command)
end
end
function main()
local files = get_test_files()
local counts = {
tests = 0,
tests_ok = 0,
checks = 0,
checks_ok = 0,
file_errors = 0,
}
local passed = true
print('Running tests')
for _, file in ipairs(files) do
print('Running file: ' .. file:sub(file:find('test'), -1))
local env, env_private = build_test_env()
local code, err = loadfile(file, 't', env)
if not code then
passed = false
counts.file_errors = counts.file_errors + 1
dfhack.printerr('Failed to load file: ' .. tostring(err))
else
local ok, err = pcall(code)
if not ok then
passed = false
counts.file_errors = counts.file_errors + 1
dfhack.printerr('Error when running file: ' .. tostring(err))
else
for name, test in pairs(env.test) do
env_private.checks = 0
env_private.checks_ok = 0
counts.tests = counts.tests + 1
local ok, err = pcall(test)
if not ok then
dfhack.printerr('test errored: ' .. name .. ': ' .. tostring(err))
passed = false
elseif env_private.checks ~= env_private.checks_ok then
dfhack.printerr('test failed: ' .. name)
passed = false
else
print('test passed: ' .. name)
counts.tests_ok = counts.tests_ok + 1
end
counts.checks = counts.checks + (tonumber(env_private.checks) or 0)
counts.checks_ok = counts.checks_ok + (tonumber(env_private.checks_ok) or 0)
end
end
end
end
print('\nTest summary:')
print(('%d/%d tests passed'):format(counts.tests_ok, counts.tests))
print(('%d/%d checks passed'):format(counts.checks_ok, counts.checks))
print(('%d test files failed to load'):format(counts.file_errors))
set_test_stage(passed and 'done' or 'fail')
finish_tests(passed)
end
local check_count = 0
function check_title()
local scr = dfhack.gui.getCurViewscreen()
if df.viewscreen_titlest:is_instance(scr) then
print('Found title screen')
main()
else
check_count = check_count + 1
if check_count > 100 then
qerror('Could not find title screen')
end
scr:feed_key(df.interface_key.LEAVESCREEN)
dfhack.timeout(10, 'frames', check_title)
end
end
set_test_stage('done')
dfhack.run_command('die')
print('Looking for title screen...')
check_title()

@ -1,4 +1,4 @@
devel/dump-rpc dfhack-rpc.txt
:lua dfhack.internal.addScriptPath(os.getenv('TRAVIS_BUILD_DIR'))
test/main
:lua dfhack.internal.addScriptPath(dfhack.getHackPath())
test/main die

@ -23,8 +23,13 @@ while True:
print('Done!')
os.remove(test_stage)
sys.exit(0)
elif stage == 'fail':
print('Failed!')
os.remove(test_stage)
sys.exit(1)
if tries > MAX_TRIES:
print('Too many tries - aborting')
sys.exit(1)
os.system(dfhack)
process = subprocess.Popen([dfhack], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
process.communicate()