From fd31d9eb03a51d6d8382b3212eeb7c5ed6f42adf Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 15:07:05 -0700 Subject: [PATCH 01/16] enable fortress mode tests in CI --- ci/test.lua | 56 ++++++++++++++++++++++++++++++----------- test/plugins/orders.lua | 2 +- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/ci/test.lua b/ci/test.lua index ac0e5718d..807572a70 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -189,39 +189,67 @@ local function ensure_title_screen() dfhack.gui.getCurFocus(true)[1])) end -local function is_fortress(focus_string) - focus_string = focus_string or dfhack.gui.getCurFocus(true) - return focus_string == 'dwarfmode/Default' +local function is_fortress() + return dfhack.gui.matchFocusString('dwarfmode/Default') +end + +local function click_top_title_button(scr) + local sw, sh = dfhack.screen.getWindowSize() + df.global.gps.mouse_x = sw // 2 + df.global.gps.precise_mouse_x = df.global.gps.mouse_x * df.global.gps.tile_pixel_x + if sh < 60 then + df.global.gps.mouse_y = 23 + else + df.global.gps.mouse_y = (sh // 2) + 1 + end + df.global.gps.precise_mouse_y = df.global.gps.mouse_y * df.global.gps.tile_pixel_y + df.global.enabler.tracking_on = 1 + df.global.enabler.mouse_lbut = 1 + df.global.enabler.mouse_lbut_down = 1 + dfhack.screen._doSimulateInput(scr, {}) +end + +local function load_first_save(scr) + if #scr.savegame_header == 0 then + qerror('no savegames available to load') + end + scr.mode = 2 + click_top_title_button(scr) + delay() + click_top_title_button(scr) + delay() end -- Requires that a fortress game is already loaded or is ready to be loaded via --- the "Continue Playing" option in the title screen. Otherwise the function +-- the "Continue active game" option in the title screen. Otherwise the function -- will time out and/or exit with error. local function ensure_fortress(config) - local focus_string = dfhack.gui.getCurFocus(true) for screen_timeout = 1,10 do - if is_fortress(focus_string) then + if is_fortress() then print('Loaded fortress map') -- pause the game (if it's not already paused) dfhack.gui.resetDwarfmodeView(true) return end - local scr = dfhack.gui.getCurViewscreen(true) - if focus_string == 'title' or - focus_string == 'dfhack/lua/load_screen' then + local scr = dfhack.gui.getDFViewscreen(true) + if dfhack.gui.matchFocusString('title') then + -- TODO: reinstate loading of a specified save dir; for now + -- just load the first possible save, which will at least let us + -- run fortress tests in CI -- qerror()'s on falure - dfhack.run_script('load-save', config.save_dir) - elseif focus_string ~= 'loadgame' then + -- dfhack.run_script('load-save', config.save_dir) + load_first_save(scr) + elseif dfhack.gui.matchFocusString('loadgame') then -- if we're not actively loading a game, hope we're in -- a screen where hitting ESC will get us to the game map -- or the title screen scr:feed_key(df.interface_key.LEAVESCREEN) end -- wait for current screen to change - local prev_focus_string = focus_string + local prev_focus_string = dfhack.gui.getCurFocus(true)[1] for frame_timeout = 1,100 do delay(10) - focus_string = dfhack.gui.getCurFocus(true) + local focus_string = dfhack.gui.getCurFocus(true)[1] if focus_string ~= prev_focus_string then goto next_screen end @@ -236,7 +264,7 @@ local function ensure_fortress(config) ::next_screen:: end qerror(string.format('Could not load fortress (timed out at %s)', - focus_string)) + table.concat(dfhack.gui.getCurFocus(), ' '))) end local MODES = { diff --git a/test/plugins/orders.lua b/test/plugins/orders.lua index c5fae8eb2..d851adb02 100644 --- a/test/plugins/orders.lua +++ b/test/plugins/orders.lua @@ -1,5 +1,5 @@ config.mode = 'fortress' ---config.target = 'orders' +config.target = 'orders' local FILE_PATH_PATTERN = 'dfhack-config/orders/%s.json' From b9a6d39b60027ddbe6efc37542b13a7227ed9f37 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 16:00:19 -0700 Subject: [PATCH 02/16] enable testing on Linux --- .github/workflows/test.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40b30cd13..e0576dbf7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,15 +67,14 @@ jobs: compiler: msvc plugins: "default" config: "empty" - # TODO: uncomment once we have a linux build we can download from bay12 - # - os: ubuntu - # compiler: gcc-10 - # plugins: "default" - # config: "default" - # - os: ubuntu - # compiler: gcc-12 - # plugins: "all" - # config: "default" + - os: ubuntu + compiler: gcc-10 + plugins: "default" + config: "default" + - os: ubuntu + compiler: gcc-12 + plugins: "all" + config: "default" steps: - name: Set env shell: bash From 621d36fd3a28074aeb53a9c36430308ad0a2a1da Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 16:16:21 -0700 Subject: [PATCH 03/16] tighen up screen matching --- ci/test.lua | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ci/test.lua b/ci/test.lua index 807572a70..5860ef5ea 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -175,6 +175,9 @@ local function ensure_title_screen() prev_ms = now_ms end end + if df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getDFViewscreen(true)) then + qerror('Cannot reach title screen from loaded fort') + end for i = 1, 100 do local scr = dfhack.gui.getCurViewscreen() if is_title_screen(scr) then @@ -193,6 +196,18 @@ local function is_fortress() return dfhack.gui.matchFocusString('dwarfmode/Default') end +-- error out if we're not running in a CI environment +-- the tests may corrupt saves, and we don't want to unexpectedly ruin a real player save +-- this heuristic is not perfect, but it should be able to detect most cases +local function ensure_ci_save(scr) + if #scr.savegame_header ~= 1 + or #scr.savegame_header_world ~= 1 + or not string.find(scr.savegame_header[0].fort_name, 'Dream') + then + qerror('Unexpected test save in slot 0; please manually load a fort for testing. note that tests may corrupt the game!') + end +end + local function click_top_title_button(scr) local sw, sh = dfhack.screen.getWindowSize() df.global.gps.mouse_x = sw // 2 @@ -232,14 +247,15 @@ local function ensure_fortress(config) return end local scr = dfhack.gui.getDFViewscreen(true) - if dfhack.gui.matchFocusString('title') then + if dfhack.gui.matchFocusString('title/Default') then -- TODO: reinstate loading of a specified save dir; for now -- just load the first possible save, which will at least let us -- run fortress tests in CI -- qerror()'s on falure -- dfhack.run_script('load-save', config.save_dir) + ensure_ci_save(scr) load_first_save(scr) - elseif dfhack.gui.matchFocusString('loadgame') then + elseif not dfhack.gui.matchFocusString('loadgame') then -- if we're not actively loading a game, hope we're in -- a screen where hitting ESC will get us to the game map -- or the title screen From 4ffa78c96c336c900801fe0d1fd88a1dfbd0342a Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 16:23:30 -0700 Subject: [PATCH 04/16] fix DF extraction on Linux --- ci/download-df.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ci/download-df.sh b/ci/download-df.sh index 12e9a41e3..399b75714 100755 --- a/ci/download-df.sh +++ b/ci/download-df.sh @@ -18,7 +18,7 @@ elif test "$OS_TARGET" = "ubuntu"; then WGET=wget df_url="${df_url}_linux.tar.bz2" df_archive_name="df.tar.bz2" - df_extract_cmd="tar -x -j --strip-components=1 -f" + df_extract_cmd="tar -x -j -C ${DF_FOLDER} -f" else echo "Unhandled OS target: ${OS_TARGET}" exit 1 @@ -29,22 +29,25 @@ if ! $WGET -v "$df_url" -O "$df_archive_name"; then exit 1 fi +md5sum "$df_archive_name" + save_url="https://dffd.bay12games.com/download.php?id=15434&f=dreamfort.7z" save_archive_name="test_save.7z" -save_extract_cmd="7z x -oDF/save" +save_extract_cmd="7z x -o${DF_FOLDER}/save" if ! $WGET -v "$save_url" -O "$save_archive_name"; then echo "Failed to download test save from $save_url" exit 1 fi +md5sum "$save_archive_name" + echo Extracting +mkdir -p ${DF_FOLDER} $df_extract_cmd "$df_archive_name" $save_extract_cmd "$save_archive_name" -mv DF/save/* DF/save/region1 +mv ${DF_FOLDER}/save/* ${DF_FOLDER}/save/region1 echo Done ls -l - -md5sum "$df_archive_name" "$save_archive_name" From 92b35e32cb7330e10e8661181854110353a0cc44 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 17:01:06 -0700 Subject: [PATCH 05/16] wait for initial load when transitioning states --- ci/test.lua | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/ci/test.lua b/ci/test.lua index 5860ef5ea..06dee5a75 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -151,18 +151,14 @@ end test_envvars.require = clean_require test_envvars.reqscript = clean_reqscript -local function is_title_screen(scr) - scr = scr or dfhack.gui.getCurViewscreen() - return df.viewscreen_titlest:is_instance(scr) +local function is_title_screen() + return dfhack.gui.matchFocusString('title/Default') end --- This only handles pre-fortress-load screens. It will time out if the player --- has already loaded a fortress or is in any screen that can't get to the title --- screen by sending ESC keys. -local function ensure_title_screen() +local function wait_for_game_load() local start_ms = dfhack.getTickCount() local prev_ms = start_ms - while df.viewscreen_initial_prepst:is_instance(dfhack.gui.getCurViewscreen()) do + while df.viewscreen_initial_prepst:is_instance(dfhack.gui.getDFViewscreen()) do delay(10) -- wait up to 1 minute for the game to load and show the title screen local now_ms = dfhack.getTickCount() @@ -175,12 +171,19 @@ local function ensure_title_screen() prev_ms = now_ms end end +end + +-- This only handles pre-fortress-load screens. It will time out if the player +-- has already loaded a fortress or is in any screen that can't get to the title +-- screen by sending ESC keys. +local function ensure_title_screen() + wait_for_game_load() if df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getDFViewscreen(true)) then qerror('Cannot reach title screen from loaded fort') end for i = 1, 100 do local scr = dfhack.gui.getCurViewscreen() - if is_title_screen(scr) then + if is_title_screen() then print('Found title screen') return end @@ -239,15 +242,17 @@ end -- the "Continue active game" option in the title screen. Otherwise the function -- will time out and/or exit with error. local function ensure_fortress(config) + wait_for_game_load() for screen_timeout = 1,10 do if is_fortress() then - print('Loaded fortress map') + print('Fortress map is loaded') -- pause the game (if it's not already paused) dfhack.gui.resetDwarfmodeView(true) return end local scr = dfhack.gui.getDFViewscreen(true) if dfhack.gui.matchFocusString('title/Default') then + print('Attempting to load the test fortress') -- TODO: reinstate loading of a specified save dir; for now -- just load the first possible save, which will at least let us -- run fortress tests in CI From 8b3a3d4ebbbec670bffc712c1753d948cb28aad7 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 17:05:08 -0700 Subject: [PATCH 06/16] reduce tries to one so we don't lose stdout other option: save stdout after every run and concatenate at the end --- ci/run-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/run-tests.py b/ci/run-tests.py index 3d646a2f7..257359324 100755 --- a/ci/run-tests.py +++ b/ci/run-tests.py @@ -31,7 +31,7 @@ if args.test_dir is not None: if not os.path.isdir(args.test_dir): print('ERROR: invalid test folder: %r' % args.test_dir) -MAX_TRIES = 5 +MAX_TRIES = 1 dfhack = 'Dwarf Fortress.exe' if sys.platform == 'win32' else './dfhack' test_status_file = 'test_status.json' From 32bd04f83e3498e1134d290283ece53e76d1c00b Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 17:16:13 -0700 Subject: [PATCH 07/16] install SDL2 on Linux for DF --- .github/workflows/test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e0576dbf7..fb7bcce7d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,6 +79,11 @@ jobs: - name: Set env shell: bash run: echo "DF_FOLDER=DF" >> $GITHUB_ENV + - name: Install dependencies + if: matrix.os == 'ubuntu' + run: | + sudo apt-get update + sudo apt-get install libsdl2-dev libsdl2-image-dev - name: Clone DFHack uses: actions/checkout@v3 with: From 0d7f9a401f7670d6e866de3096813ea0529421be Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 17:54:10 -0700 Subject: [PATCH 08/16] output where we're clicking for debugging --- ci/test.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/test.lua b/ci/test.lua index 06dee5a75..57ed13124 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -220,6 +220,7 @@ local function click_top_title_button(scr) else df.global.gps.mouse_y = (sh // 2) + 1 end + print(('simulating click at screen coordinates %d, %d'):format(df.global.gps.mouse_x, df.global.gps.mouse_y)) df.global.gps.precise_mouse_y = df.global.gps.mouse_y * df.global.gps.tile_pixel_y df.global.enabler.tracking_on = 1 df.global.enabler.mouse_lbut = 1 From b3fdaa54c558e9ff72bd8bf51c973e5b09c07e9d Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 22:00:03 -0700 Subject: [PATCH 09/16] install non-dev libs; start X server --- .github/workflows/test.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb7bcce7d..d36ff49d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -83,7 +83,9 @@ jobs: if: matrix.os == 'ubuntu' run: | sudo apt-get update - sudo apt-get install libsdl2-dev libsdl2-image-dev + sudo apt-get install \ + libsdl2-2.0-0 \ + libsdl2-image-2.0-0 - name: Clone DFHack uses: actions/checkout@v3 with: @@ -121,8 +123,13 @@ jobs: - name: Install DFHack shell: bash run: tar xjf test-${{ matrix.compiler }}.tar.bz2 -C ${{ env.DF_FOLDER }} + - name: Start X server + if: matrix.os == 'ubuntu' + run: Xvfb :0 -screen 0 1600x1200x32 & - name: Run lua tests timeout-minutes: 10 + env: + DISPLAY: :0 run: python ci/run-tests.py --keep-status "${{ env.DF_FOLDER }}" - name: Check RPC interface run: python ci/check-rpc.py "${{ env.DF_FOLDER }}/dfhack-rpc.txt" From e8f0de4078efbbdec0150823e8418d6006bfb9b4 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 22:00:15 -0700 Subject: [PATCH 10/16] print screen dims --- ci/test.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/test.lua b/ci/test.lua index 57ed13124..34fcd97a6 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -213,6 +213,7 @@ end local function click_top_title_button(scr) local sw, sh = dfhack.screen.getWindowSize() + print(('screen dimensions: %d, %d'):format(sw. sh)) df.global.gps.mouse_x = sw // 2 df.global.gps.precise_mouse_x = df.global.gps.mouse_x * df.global.gps.tile_pixel_x if sh < 60 then From 8dc5f8e86b23746aea2912b02039f2de30a7d636 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 23:23:49 -0700 Subject: [PATCH 11/16] fix screen depth and print syntax --- .github/workflows/test.yml | 2 +- ci/test.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d36ff49d4..fa59c5f2e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -125,7 +125,7 @@ jobs: run: tar xjf test-${{ matrix.compiler }}.tar.bz2 -C ${{ env.DF_FOLDER }} - name: Start X server if: matrix.os == 'ubuntu' - run: Xvfb :0 -screen 0 1600x1200x32 & + run: Xvfb :0 -screen 0 1600x1200x24 & - name: Run lua tests timeout-minutes: 10 env: diff --git a/ci/test.lua b/ci/test.lua index 34fcd97a6..193b89ce8 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -213,7 +213,7 @@ end local function click_top_title_button(scr) local sw, sh = dfhack.screen.getWindowSize() - print(('screen dimensions: %d, %d'):format(sw. sh)) + print(('screen dimensions: %d, %d'):format(sw, sh)) df.global.gps.mouse_x = sw // 2 df.global.gps.precise_mouse_x = df.global.gps.mouse_x * df.global.gps.tile_pixel_x if sh < 60 then From 989415cef08b420d6e19e8f81b9a7fd1d641baac Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 24 Sep 2023 23:45:43 -0700 Subject: [PATCH 12/16] use gui.simulateInput --- ci/test.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/test.lua b/ci/test.lua index 193b89ce8..dc814da19 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -2,6 +2,7 @@ --@ module = true local expect = require('test_util.expect') +local gui = require('gui') local helpdb = require('helpdb') local json = require('json') local mock = require('test_util.mock') @@ -226,7 +227,7 @@ local function click_top_title_button(scr) df.global.enabler.tracking_on = 1 df.global.enabler.mouse_lbut = 1 df.global.enabler.mouse_lbut_down = 1 - dfhack.screen._doSimulateInput(scr, {}) + gui.simulateInput(scr, '_MOUSE_L') end local function load_first_save(scr) From 9cd90589822cbc6bc2adee1e90b543293b27adcc Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 25 Sep 2023 00:04:29 -0700 Subject: [PATCH 13/16] set a TERM var --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa59c5f2e..6255219e6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -130,6 +130,7 @@ jobs: timeout-minutes: 10 env: DISPLAY: :0 + TERM: xterm-256color run: python ci/run-tests.py --keep-status "${{ env.DF_FOLDER }}" - name: Check RPC interface run: python ci/check-rpc.py "${{ env.DF_FOLDER }}/dfhack-rpc.txt" From 0c1d73cfe63bd86e1061ae22eabe42619636a61a Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 25 Sep 2023 00:04:41 -0700 Subject: [PATCH 14/16] adjust settings to v50 norms --- ci/run-tests.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ci/run-tests.py b/ci/run-tests.py index 257359324..f43c7efd4 100755 --- a/ci/run-tests.py +++ b/ci/run-tests.py @@ -65,14 +65,12 @@ if not os.path.exists(init_txt_path): shutil.copyfile(init_txt_path, init_txt_path + '.orig') with open(init_txt_path) as f: init_contents = f.read() -init_contents = change_setting(init_contents, 'INTRO', 'NO') init_contents = change_setting(init_contents, 'SOUND', 'NO') init_contents = change_setting(init_contents, 'WINDOWED', 'YES') -init_contents = change_setting(init_contents, 'WINDOWEDX', '80') -init_contents = change_setting(init_contents, 'WINDOWEDY', '25') -init_contents = change_setting(init_contents, 'FPS', 'YES') -if args.headless: - init_contents = change_setting(init_contents, 'PRINT_MODE', 'TEXT') +init_contents = change_setting(init_contents, 'WINDOWEDX', '1200') +init_contents = change_setting(init_contents, 'WINDOWEDY', '800') +#if args.headless: +# init_contents = change_setting(init_contents, 'PRINT_MODE', 'TEXT') init_path = 'dfhack-config/init' if not os.path.isdir('hack/init'): From cc49c07870d2585b0ec625354cb2020cb0193c23 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 25 Sep 2023 12:07:39 -0700 Subject: [PATCH 15/16] click on buttons to drive the UI --- ci/test.lua | 69 +++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/ci/test.lua b/ci/test.lua index dc814da19..3b5b041ba 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -156,19 +156,18 @@ local function is_title_screen() return dfhack.gui.matchFocusString('title/Default') end -local function wait_for_game_load() +local function wait_for(ms, desc, predicate) local start_ms = dfhack.getTickCount() local prev_ms = start_ms - while df.viewscreen_initial_prepst:is_instance(dfhack.gui.getDFViewscreen()) do + while not predicate() do delay(10) - -- wait up to 1 minute for the game to load and show the title screen local now_ms = dfhack.getTickCount() - if now_ms - start_ms > 60000 then - qerror(('Could not find title screen (timed out at %s)'):format( - dfhack.gui.getCurFocus(true)[1])) + if now_ms - start_ms > ms then + qerror(('%s took too long (timed out at %s)'):format( + desc, dfhack.gui.getCurFocus(true)[1])) end if now_ms - prev_ms > 1000 then - print('Waiting for game to load and show title screen...') + print(('Waiting for %s...'):format(desc)) prev_ms = now_ms end end @@ -178,7 +177,6 @@ end -- has already loaded a fortress or is in any screen that can't get to the title -- screen by sending ESC keys. local function ensure_title_screen() - wait_for_game_load() if df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getDFViewscreen(true)) then qerror('Cannot reach title screen from loaded fort') end @@ -208,21 +206,21 @@ local function ensure_ci_save(scr) or #scr.savegame_header_world ~= 1 or not string.find(scr.savegame_header[0].fort_name, 'Dream') then - qerror('Unexpected test save in slot 0; please manually load a fort for testing. note that tests may corrupt the game!') + qerror('Unexpected test save in slot 0; please manually load a fort for ' .. + 'running fortress mode tests. note that tests may alter or corrupt the ' .. + 'fort! Do not save after running tests.') end end local function click_top_title_button(scr) local sw, sh = dfhack.screen.getWindowSize() - print(('screen dimensions: %d, %d'):format(sw, sh)) df.global.gps.mouse_x = sw // 2 df.global.gps.precise_mouse_x = df.global.gps.mouse_x * df.global.gps.tile_pixel_x if sh < 60 then - df.global.gps.mouse_y = 23 + df.global.gps.mouse_y = 25 else - df.global.gps.mouse_y = (sh // 2) + 1 + df.global.gps.mouse_y = (sh // 2) + 3 end - print(('simulating click at screen coordinates %d, %d'):format(df.global.gps.mouse_x, df.global.gps.mouse_y)) df.global.gps.precise_mouse_y = df.global.gps.mouse_y * df.global.gps.tile_pixel_y df.global.enabler.tracking_on = 1 df.global.enabler.mouse_lbut = 1 @@ -234,18 +232,25 @@ local function load_first_save(scr) if #scr.savegame_header == 0 then qerror('no savegames available to load') end - scr.mode = 2 + click_top_title_button(scr) - delay() + wait_for(1000, 'world list', function() + return scr.mode == 2 + end) click_top_title_button(scr) - delay() + wait_for(1000, 'savegame list', function() + return scr.mode == 3 + end) + click_top_title_button(scr) + wait_for(1000, 'loadgame progress bar', function() + return dfhack.gui.matchFocusString('loadgame') + end) end -- Requires that a fortress game is already loaded or is ready to be loaded via -- the "Continue active game" option in the title screen. Otherwise the function -- will time out and/or exit with error. local function ensure_fortress(config) - wait_for_game_load() for screen_timeout = 1,10 do if is_fortress() then print('Fortress map is loaded') @@ -253,8 +258,8 @@ local function ensure_fortress(config) dfhack.gui.resetDwarfmodeView(true) return end - local scr = dfhack.gui.getDFViewscreen(true) - if dfhack.gui.matchFocusString('title/Default') then + local scr = dfhack.gui.getCurViewscreen() + if dfhack.gui.matchFocusString('title/Default', scr) then print('Attempting to load the test fortress') -- TODO: reinstate loading of a specified save dir; for now -- just load the first possible save, which will at least let us @@ -263,29 +268,17 @@ local function ensure_fortress(config) -- dfhack.run_script('load-save', config.save_dir) ensure_ci_save(scr) load_first_save(scr) - elseif not dfhack.gui.matchFocusString('loadgame') then + elseif not dfhack.gui.matchFocusString('loadgame', scr) then -- if we're not actively loading a game, hope we're in -- a screen where hitting ESC will get us to the game map -- or the title screen scr:feed_key(df.interface_key.LEAVESCREEN) end -- wait for current screen to change - local prev_focus_string = dfhack.gui.getCurFocus(true)[1] - for frame_timeout = 1,100 do - delay(10) - local focus_string = dfhack.gui.getCurFocus(true)[1] - if focus_string ~= prev_focus_string then - goto next_screen - end - if frame_timeout % 10 == 0 then - print(string.format( - 'Loading fortress (currently at screen: %s)', - focus_string)) - end - end - print('Timed out waiting for screen to change') - break - ::next_screen:: + local prev_focus_string = dfhack.gui.getCurFocus()[1] + wait_for(60000, 'screen change', function() + return dfhack.gui.getCurFocus()[1] ~= prev_focus_string + end) end qerror(string.format('Could not load fortress (timed out at %s)', table.concat(dfhack.gui.getCurFocus(), ' '))) @@ -630,6 +623,10 @@ local function filter_tests(tests, config) end local function run_tests(tests, status, counts, config) + wait_for(60000, 'game load', function() + local scr = dfhack.gui.getDFViewscreen() + return not df.viewscreen_initial_prepst:is_instance(scr) + end) print(('Running %d tests'):format(#tests)) local start_ms = dfhack.getTickCount() local num_skipped = 0 From 30e3b695a17b215a9c10a11c51d29a91ac74f189 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 25 Sep 2023 17:34:38 -0700 Subject: [PATCH 16/16] skip crashing tests and mark them as failed --- ci/run-tests.py | 2 +- ci/test.lua | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ci/run-tests.py b/ci/run-tests.py index f43c7efd4..13eeb099c 100755 --- a/ci/run-tests.py +++ b/ci/run-tests.py @@ -31,7 +31,7 @@ if args.test_dir is not None: if not os.path.isdir(args.test_dir): print('ERROR: invalid test folder: %r' % args.test_dir) -MAX_TRIES = 1 +MAX_TRIES = 5 dfhack = 'Dwarf Fortress.exe' if sys.platform == 'win32' else './dfhack' test_status_file = 'test_status.json' diff --git a/ci/test.lua b/ci/test.lua index 3b5b041ba..372d8f262 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -645,12 +645,13 @@ local function run_tests(tests, status, counts, config) goto skip end end + -- pre-emptively mark the test as failed in case we induce a crash + status[test.full_name] = TestStatus.FAILED + save_test_status(status) if run_test(test, status, counts) then status[test.full_name] = TestStatus.PASSED - else - status[test.full_name] = TestStatus.FAILED + save_test_status(status) end - save_test_status(status) ::skip:: end local elapsed_ms = dfhack.getTickCount() - start_ms