mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-09-22 22:58:12 +03:00
Add headless scenario tests
Run a compiled System 1/2/3 scenarios with SDL's dummy video and audio drivers, and report failures through the text hook and exit status.
This commit is contained in:
@@ -17,11 +17,12 @@ jobs:
|
||||
- name: Install Deps
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libsdl2-dev libsdl2-ttf-dev librtmidi-dev nlohmann-json3-dev
|
||||
sudo apt install libsdl2-dev libsdl2-ttf-dev librtmidi-dev nlohmann-json3-dev ninja-build
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p out/${{ matrix.build-type }}
|
||||
cd out/${{ matrix.build-type }}
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} ../../
|
||||
make -j4
|
||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build-type }}
|
||||
cmake --build build
|
||||
|
||||
- name: Test
|
||||
run: ctest --output-on-failure --test-dir build
|
||||
|
||||
@@ -51,6 +51,9 @@ jobs:
|
||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=YES
|
||||
cmake --build build
|
||||
|
||||
- name: Test
|
||||
run: ctest --output-on-failure --test-dir build
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
cp build/system3.exe COPYING.txt dist/
|
||||
|
||||
@@ -7,6 +7,7 @@ endif ()
|
||||
|
||||
project(System3 LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
include(CTest)
|
||||
|
||||
# Generates a static library from pkg_check_modules() result
|
||||
function(add_static_library name pkg)
|
||||
@@ -250,3 +251,7 @@ endif()
|
||||
|
||||
target_compile_definitions(system3 PRIVATE RESOURCE_PATH="${RESOURCE_PATH}")
|
||||
target_include_directories(system3 PRIVATE src src/sys)
|
||||
|
||||
if (BUILD_TESTING AND NOT ANDROID AND NOT EMSCRIPTEN AND NOT NINTENDO_SWITCH)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
+4
-1
@@ -96,6 +96,7 @@ const struct CRCTable {
|
||||
uint32 crc32_a;
|
||||
uint32 crc32_b;
|
||||
} crc_table[] = {
|
||||
{GameId::SYSTEM1_GENERIC, "system1_generic", 1, "System 1", JAPANESE},
|
||||
{GameId::BUNKASAI, "bunkasai", 1, "あぶない文化祭前夜", JAPANESE, CRC32_BUNKASAI},
|
||||
{GameId::CRESCENT, "crescent", 1, "クレセントムーンがぁる", JAPANESE, CRC32_CRESCENT},
|
||||
{GameId::DPS, "dps", 1, "D.P.S - Dream Program System", JAPANESE, CRC32_DPS},
|
||||
@@ -122,6 +123,7 @@ const struct CRCTable {
|
||||
{GameId::GAKUEN, "gakuen", 1, "学園戦記", JAPANESE, CRC32_GAKUEN},
|
||||
{GameId::GAKUEN, "gakuen_eng", 1, "Gakuen Senki", ENGLISH, CRC32_GAKUEN_ENG},
|
||||
|
||||
{GameId::SYSTEM2_GENERIC, "system2_generic", 2, "System 2", JAPANESE},
|
||||
{GameId::AYUMI_FD, "ayumi_fd", 2, "あゆみちゃん物語", JAPANESE, CRC32_AYUMI_FD},
|
||||
{GameId::AYUMI_HINT, "ayumi_hint", 2, "あゆみちゃん物語 ヒントディスク", JAPANESE, CRC32_AYUMI_HINT},
|
||||
{GameId::AYUMI_PROTO, "ayumi_proto", 2, "あゆみちゃん物語 PROTO", JAPANESE, CRC32_AYUMI_PROTO},
|
||||
@@ -138,6 +140,7 @@ const struct CRCTable {
|
||||
{GameId::SDPS_KAIZOKU, "sdps_kaizoku", 2, "Super D.P.S - うれしたのし海賊稼業", JAPANESE, CRC32_SDPS, CRC32_SDPS_KAIZOKU},
|
||||
{GameId::YAKATA2, "yakata2", 2, "ALICEの館II", JAPANESE, CRC32_YAKATA2},
|
||||
|
||||
{GameId::SYSTEM3_GENERIC, "system3_generic", 3, "System 3", JAPANESE},
|
||||
{GameId::AMBIVALENZ_FD, "ambivalenz_fd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_FD},
|
||||
{GameId::AMBIVALENZ_CD, "ambivalenz_cd", 3, "AmbivalenZ −二律背反−", JAPANESE, CRC32_AMBIVALENZ_CD},
|
||||
{GameId::DPS_ALL, "dps_all", 3, "D.P.S. 全部", JAPANESE, CRC32_DPSALL},
|
||||
@@ -172,7 +175,7 @@ const struct CRCTable {
|
||||
const CRCTable* lookup(uint32 crc32_a, uint32 crc32_b)
|
||||
{
|
||||
for (const CRCTable* t = crc_table; t->id; t++) {
|
||||
if (crc32_a == t->crc32_a && (!t->crc32_b || crc32_b == t->crc32_b))
|
||||
if (t->crc32_a && crc32_a == t->crc32_a && (!t->crc32_b || crc32_b == t->crc32_b))
|
||||
return t;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -15,6 +15,7 @@ struct GameId {
|
||||
UNKNOWN,
|
||||
|
||||
// System 1
|
||||
SYSTEM1_GENERIC,
|
||||
BUNKASAI,
|
||||
CRESCENT,
|
||||
DPS,
|
||||
@@ -40,6 +41,7 @@ struct GameId {
|
||||
GAKUEN,
|
||||
|
||||
// System 2
|
||||
SYSTEM2_GENERIC,
|
||||
AYUMI_FD,
|
||||
AYUMI_HINT,
|
||||
AYUMI_PROTO,
|
||||
@@ -57,6 +59,7 @@ struct GameId {
|
||||
YAKATA2,
|
||||
|
||||
// System 3
|
||||
SYSTEM3_GENERIC,
|
||||
AMBIVALENZ_FD,
|
||||
AMBIVALENZ_CD,
|
||||
DPS_ALL,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
function(add_scenario_test system)
|
||||
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/scenario/${system})
|
||||
file(MAKE_DIRECTORY ${TEST_DIR})
|
||||
configure_file(scenario/${system}/ADISK.DAT ${TEST_DIR}/ADISK.DAT COPYONLY)
|
||||
|
||||
add_test(
|
||||
NAME scenario_${system}
|
||||
COMMAND $<TARGET_FILE:system3>
|
||||
-gamedir ${TEST_DIR}
|
||||
-game ${system}_generic
|
||||
-encoding utf8
|
||||
-fontfile ${PROJECT_SOURCE_DIR}/resources/fonts/MTLc3m.ttf
|
||||
-texthook print
|
||||
)
|
||||
set_tests_properties(scenario_${system} PROPERTIES
|
||||
ENVIRONMENT "SDL_VIDEODRIVER=dummy;SDL_AUDIODRIVER=dummy"
|
||||
FAIL_REGULAR_EXPRESSION "\\[FAIL\\]"
|
||||
PASS_REGULAR_EXPRESSION "(^|[^0-9])0 tests failed"
|
||||
TIMEOUT 5
|
||||
)
|
||||
endfunction()
|
||||
|
||||
add_scenario_test(system1)
|
||||
add_scenario_test(system2)
|
||||
add_scenario_test(system3)
|
||||
@@ -0,0 +1,16 @@
|
||||
# Scenario tests
|
||||
|
||||
The scenario tests run compiled System 1, 2, and 3 scenarios through the
|
||||
normal engine with SDL's dummy video and audio drivers. CTest checks both the
|
||||
process exit status and the `0 tests failed` summary printed through the text
|
||||
hook.
|
||||
|
||||
`ADISK.DAT` is checked in so that building and running the tests does not
|
||||
require [sys3c](https://github.com/kichikuou/sys3c). After installing sys3c
|
||||
and changing the scenario sources, regenerate it with:
|
||||
|
||||
```sh
|
||||
for system in system1 system2 system3; do
|
||||
(cd test/scenario/$system && sys3c)
|
||||
done
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
; Addition and saturating overflow.
|
||||
{3 + 4 \ 7: !tests_failed : tests_failed + 1! '[FAIL] addition' R}
|
||||
{50000 + 50000 \ 65535: !tests_failed : tests_failed + 1! '[FAIL] addition overflow' R}
|
||||
|
||||
; Subtraction saturates at zero.
|
||||
{10 - 3 \ 7: !tests_failed : tests_failed + 1! '[FAIL] subtraction' R}
|
||||
{3 - 10 \ 0: !tests_failed : tests_failed + 1! '[FAIL] subtraction underflow' R}
|
||||
|
||||
; Multiplication and precedence.
|
||||
{3 * 4 \ 12: !tests_failed : tests_failed + 1! '[FAIL] multiplication' R}
|
||||
{1000 * 1000 \ 65535: !tests_failed : tests_failed + 1! '[FAIL] multiplication overflow' R}
|
||||
{2 + 3 * 4 \ 14: !tests_failed : tests_failed + 1! '[FAIL] precedence' R}
|
||||
{(2 + 3) * 4 \ 20: !tests_failed : tests_failed + 1! '[FAIL] parentheses' R}
|
||||
|
||||
; Comparisons.
|
||||
{3 < 4 \ 1: !tests_failed : tests_failed + 1! '[FAIL] less than' R}
|
||||
{4 < 3 \ 0: !tests_failed : tests_failed + 1! '[FAIL] false less than' R}
|
||||
{4 > 3 \ 1: !tests_failed : tests_failed + 1! '[FAIL] greater than' R}
|
||||
{3 \ 3: !tests_failed : tests_failed + 1! '[FAIL] equality' R}
|
||||
{3 = 4: !tests_failed : tests_failed + 1! '[FAIL] inequality' R}
|
||||
|
||||
; Variables use the same expression evaluator.
|
||||
!actual : 40!
|
||||
!expected : 42!
|
||||
!actual : actual + 2!
|
||||
{actual \ expected: !tests_failed : tests_failed + 1! '[FAIL] variables' R}
|
||||
|
||||
%0:
|
||||
|
||||
*default:
|
||||
EOF
|
||||
@@ -0,0 +1,7 @@
|
||||
{10 / 3 \ 3: !tests_failed : tests_failed + 1! '[FAIL] division' R}
|
||||
{10 / 0 \ 0: !tests_failed : tests_failed + 1! '[FAIL] division by zero' R}
|
||||
|
||||
%0:
|
||||
|
||||
*default:
|
||||
EOF
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
game = system1_generic
|
||||
hed = test.hed
|
||||
encoding = utf8
|
||||
unicode = true
|
||||
@@ -0,0 +1,14 @@
|
||||
!RND : 0!
|
||||
!tests_failed : 0!
|
||||
|
||||
Y 240, 1:
|
||||
|
||||
%#arithmetic.adv:
|
||||
|
||||
; System 1 cannot return the failure count as its process exit status.
|
||||
; Print the success marker only when every assertion passed.
|
||||
{tests_failed = 0: '0 tests failed' R}
|
||||
Y 253, 0:
|
||||
|
||||
*default:
|
||||
EOF
|
||||
@@ -0,0 +1,2 @@
|
||||
test.adv
|
||||
../common/arithmetic.adv
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
game = system2_generic
|
||||
hed = test.hed
|
||||
encoding = utf8
|
||||
unicode = true
|
||||
@@ -0,0 +1,14 @@
|
||||
!RND : 0!
|
||||
!tests_failed : 0!
|
||||
|
||||
Y 240, 1:
|
||||
|
||||
%#arithmetic.adv:
|
||||
%#division.adv:
|
||||
|
||||
H 0, tests_failed: ' tests failed' R
|
||||
!RND : tests_failed!
|
||||
Y 255, 0:
|
||||
|
||||
*default:
|
||||
EOF
|
||||
@@ -0,0 +1,3 @@
|
||||
test.adv
|
||||
../common/arithmetic.adv
|
||||
../common/division.adv
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
game = system3_generic
|
||||
hed = test.hed
|
||||
encoding = utf8
|
||||
unicode = true
|
||||
@@ -0,0 +1,16 @@
|
||||
!RND : 0!
|
||||
!tests_failed : 0!
|
||||
|
||||
; System3-sdl2 extension: draw ASCII as half-width characters so the
|
||||
; text-hook output is easy for CTest and humans to read.
|
||||
Y 240, 1:
|
||||
|
||||
%#arithmetic.adv:
|
||||
%#division.adv:
|
||||
|
||||
H 0, tests_failed: ' tests failed' R
|
||||
!RND : tests_failed!
|
||||
Y 255, 0:
|
||||
|
||||
*default:
|
||||
EOF
|
||||
@@ -0,0 +1,3 @@
|
||||
test.adv
|
||||
../common/arithmetic.adv
|
||||
../common/division.adv
|
||||
Reference in New Issue
Block a user