Compare commits

...

5 commits

Author SHA1 Message Date
Lukas Brübach
976a4a9a7e [Tests] Link gtest_main on the fetched-gtest path
The downloaded-gtest branch set GTEST_BOTH_LIBRARIES to `gtest` alone, while
FindGTest sets it to both halves. Every test target links that list rather than
picking an entry point, so on this path nothing provides main() and any test
source that does not define its own fails at link with `undefined reference to
main` pointing at crt1.o, naming neither gtest nor the line responsible.

That stayed latent while every test carried its own four-line main(). A test that
omits it now fails, and the error points at the C runtime rather than at gtest,
which is a long way from the cause. Restoring both halves makes the two paths
agree and drops the boilerplate requirement on new test sources.

The 18 sources that still define main() keep linking: gtest_main.cc defines
nothing but main, so the linker leaves its object in the archive unused rather
than reporting a duplicate.
2026-10-05 14:44:20 +02:00
Lukas Brübach
5aafeffe4c [Tests] Carry one CTest label per test instead of several
gtest_discover_tests() can hand CTest exactly one label. GoogleTestAddTests.cmake
accumulates its generated script with `foreach(arg ${ARGN})`, so a label list reaches
the CTestTestfile as bare `LABELS ci server`, and CTest reads only the first value of a
property and drops the rest without a word.

The `ci` label that is appended to every registered test was therefore absent from every
test that also asked for `server` or `bench`: `ctest -L ci` reported 400 of 469 cases,
and `ctest --print-labels` never listed a second label anywhere in the build.

Reduce each test to exactly one of `ci`, `server`, or `bench`, which is all the
selections need. The three now partition the suite exactly, 400 + 64 + 5 = 469, and
`ctest -LE bench` still means everything but benchmarks. A second label is now a
configure-time FATAL_ERROR rather than a line that quietly means something else.

Anything orthogonal to a test's kind belongs in a helper flag beside the label, so it
composes with the group instead of competing for the single slot.

Also raise DISCOVERY_TIMEOUT off GoogleTestAddTests' 5s default. A plain debug binary
answers --gtest_list_tests in 0.04s, but that budget is thin once several binaries
discover concurrently behind a -j build, and being over it fails at the *link* step with
a bare "Process terminated due to timeout" that points nowhere near the cause.
2026-10-05 09:48:22 +02:00
Lukas Brübach
5ff88c1cf3 [Tests] Correct the note on the oracle test compression defines
add_definitions() populates the directory's COMPILE_DEFINITIONS property, which is
consumed at generate time, so it reaches every target in the directory no matter
where it is called relative to add_executable(). The previous note claimed the
flags stayed confined to the benchmark because the find_package block came after
it; oracle_importer_test, created above that block, carries both defines too.

Verified harmless rather than a live bug: HAS_ZLIB and HAS_LZMA gate code only in
oracle/src/pages.cpp and oracle/src/pagetemplates.cpp, and no test target compiles
either. The ordering and the leaked defines are both pre-existing, so this only
corrects the explanation.
2026-10-05 08:23:50 +02:00
Lukas Brübach
fbfd85c8e7 [Tests] Make QtTest available to test targets
QtTest was not among the modules test targets could link, so the Qt model and
signal contracts had no way to be verified from a test: QAbstractItemModelTester
and QSignalSpy both live there.

Add Test to _TEST_NEEDED in cmake/FindQtRuntime.cmake. That is the single place the
union of test-only Qt modules is declared, so this is the only file that needs to
change to make the module reachable from every test target.

Nothing uses it yet. This lands the capability ahead of the model-layer tests that
need it, so those can be added as tests alone rather than as test plus build-system
plumbing.
2026-10-05 08:20:19 +02:00
Lukas Brübach
b7a6f54103 [Tests] Register each test case with CTest instead of each test binary
Registering a test cost four edits across a dozen CMakeLists files: add_test,
add_executable, a conditional add_dependencies on gtest, and target_link_libraries.
The conditional branch was the trap -- it is only needed when GTest was fetched and
add_subdirectory'd, and omitting it yields undefined gtest symbols at link time --
so it was easy to leave out and impossible to notice until the link failed.

Fold all four steps into cockatrice_add_test() and migrate every test directory
onto it, with a cockatrice_add_manual_test() wrapper for the three benchmarks that
are built but deliberately kept out of ctest. The calls now read as a declaration
of what a test is rather than a transcript of how to register one.

While rewriting the registrations, replace add_test(NAME x COMMAND x) with
gtest_discover_tests(). Naming the binary as a single CTest entry meant a CI failure
reported only which binary failed, and ctest -R Suite.Case could not select an
individual case. Discovery raises the suite from 35 opaque entries to 469 real ones:
ctest -R ThemeMigrationTest.IsIdempotent now runs exactly that case, and
ctest -L server / -LE bench work off labels applied at registration.

Give every test a 60s TIMEOUT. CTest's implicit default is 1500s, so one hung
socket wait would stall CI for 25 minutes, and single_instance_manager_test already
does real QLocalSocket waits.

Dropping per-case granularity costs wall-clock time, since the suite becomes
process-spawn bound rather than CPU bound: serial ctest went from 3.8s to 30.8s. Run
it with -j in CI to recover it -- 7.6s at -j4, and 3.5s at -j8, both at or below
the old serial time. The binaries are parallel-safe: the only test claiming a fixed
resource scopes its local socket name to its own pid, so concurrent copies cannot
collide.

Also delete dummy_test, which asserted 1 == 1 and only proved the harness was
wired up -- something the other 468 cases already establish.

No test is added, removed, or changed by this commit; the 469 cases are the same
ones the 35 binaries contained.
2026-10-05 08:20:09 +02:00
14 changed files with 417 additions and 391 deletions

View file

@ -306,7 +306,11 @@ fi
if [[ $MAKE_TEST ]]; then if [[ $MAKE_TEST ]]; then
echo "::group::Run tests" echo "::group::Run tests"
ctest -C "$BUILDTYPE" --output-on-failure # Every TEST() is its own CTest entry, so the suite is process-spawn bound rather than CPU
# bound and -j recovers nearly all of the per-process overhead. The test binaries are safe to
# run concurrently: the only one that claims a fixed resource is single_instance_manager_test,
# which already scopes its local socket name to its own pid so parallel copies cannot collide.
ctest -C "$BUILDTYPE" --output-on-failure -j "${CTEST_JOBS:-4}"
echo "::endgroup::" echo "::endgroup::"
fi fi

View file

@ -33,7 +33,9 @@ endif()
if(TEST) if(TEST)
# Union of Qt modules required across all test targets (independent of application targets). # Union of Qt modules required across all test targets (independent of application targets).
# When adding a new test that needs additional Qt modules, add them here rather than in the test's CMakeLists.txt. # When adding a new test that needs additional Qt modules, add them here rather than in the test's CMakeLists.txt.
set(_TEST_NEEDED Concurrent Network Svg Widgets) # Test is QtTest: it brings QAbstractItemModelTester and QSignalSpy, which are how the Qt model
# and signal contracts get verified without standing up a GUI.
set(_TEST_NEEDED Concurrent Network Svg Widgets Test)
endif() endif()
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED} set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED}

View file

@ -2,102 +2,10 @@
# If a new test needs additional Qt modules, add them there — not in individual test CMakeLists.txt files. # If a new test needs additional Qt modules, add them there — not in individual test CMakeLists.txt files.
enable_testing() enable_testing()
add_test(NAME dummy_test COMMAND dummy_test) include(GoogleTest)
add_test(NAME expression_test COMMAND expression_test)
add_test(NAME clamped_arithmetic_test COMMAND clamped_arithmetic_test)
add_test(NAME test_age_formatting COMMAND test_age_formatting)
add_test(NAME password_hash_test COMMAND password_hash_test)
add_test(NAME playmat_resolver_test COMMAND playmat_resolver_test)
add_test(NAME server_card_counter_test COMMAND server_card_counter_test)
add_test(NAME server_counter_test COMMAND server_counter_test)
add_test(NAME server_rate_limiter_test COMMAND server_rate_limiter_test)
add_test(NAME server_developer_role_test COMMAND server_developer_role_test)
add_test(NAME server_game_join_test COMMAND server_game_join_test)
add_test(NAME warning_categories_test COMMAND warning_categories_test)
# The translation loader test compiles a .qm fixture, which needs lrelease from Qt Linguist.
if(TARGET Qt6::lrelease)
add_test(NAME translation_loader_test COMMAND translation_loader_test)
endif()
add_test(NAME report_categories_test COMMAND report_categories_test)
add_test(NAME lag_monitor_test COMMAND lag_monitor_test)
add_test(NAME latency_tracker_test COMMAND latency_tracker_test)
add_test(NAME metrics_registry_test COMMAND metrics_registry_test)
add_test(NAME loader_local_matching_test COMMAND loader_local_matching_test)
add_test(NAME deck_hash_performance_test COMMAND deck_hash_performance_test)
set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 15)
# Find GTest # Find GTest
add_executable(dummy_test dummy_test.cpp)
add_executable(expression_test expression_test.cpp)
add_executable(clamped_arithmetic_test clamped_arithmetic_test.cpp)
add_executable(test_age_formatting test_age_formatting.cpp)
add_executable(password_hash_test password_hash_test.cpp)
add_executable(playmat_resolver_test playmat_resolver_test.cpp)
add_executable(deck_hash_performance_test deck_hash_performance_test.cpp)
add_executable(server_card_counter_test server_card_counter_test.cpp)
add_executable(server_counter_test server_counter_test.cpp)
add_executable(server_rate_limiter_test server_rate_limiter_test.cpp)
add_executable(server_developer_role_test server_developer_role_test.cpp)
add_executable(server_game_join_test server_game_join_test.cpp)
add_executable(warning_categories_test warning_categories_test.cpp)
if(TARGET Qt6::lrelease)
add_executable(translation_loader_test translation_loader_test.cpp)
# QTranslator only accepts real .qm files, so the translation loader test gets one compiled from its
# own .ts fixture rather than a stub.
set(TRANSLATION_LOADER_TEST_QM "${CMAKE_CURRENT_BINARY_DIR}/translation_loader_test_de.qm")
add_custom_command(
OUTPUT "${TRANSLATION_LOADER_TEST_QM}"
COMMAND Qt6::lrelease "${CMAKE_CURRENT_SOURCE_DIR}/translation_loader_test.ts" -qm "${TRANSLATION_LOADER_TEST_QM}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/translation_loader_test.ts"
COMMENT "Compiling translation_loader_test.ts"
)
add_custom_target(translation_loader_test_qm DEPENDS "${TRANSLATION_LOADER_TEST_QM}")
add_dependencies(translation_loader_test translation_loader_test_qm)
target_compile_definitions(translation_loader_test PRIVATE TRANSLATION_LOADER_TEST_DIR="${CMAKE_CURRENT_BINARY_DIR}")
# A multi-config generator (MSBuild, Xcode) puts the executable in a per-config subdirectory while
# the .qm stays in the current binary directory, so copy the fixture next to the binary: that is the
# layout ABuildTreeFindsTheTranslationsNextToTheExecutable is about, and the only one it finds on
# those generators.
add_custom_command(
TARGET translation_loader_test
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${TRANSLATION_LOADER_TEST_QM}"
"$<TARGET_FILE_DIR:translation_loader_test>/"
VERBATIM
)
endif()
add_executable(report_categories_test report_categories_test.cpp)
add_executable(lag_monitor_test ${CMAKE_SOURCE_DIR}/cockatrice/src/client/lag_monitor.cpp lag_monitor_test.cpp)
target_include_directories(lag_monitor_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
add_executable(latency_tracker_test latency_tracker_test.cpp)
add_executable(metrics_registry_test ../servatrice/src/metrics_registry.cpp metrics_registry_test.cpp)
add_executable(
loader_local_matching_test
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/cache_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/card_counter_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/shortcuts_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp
${VERSION_STRING_CPP}
loader_local_matching_test.cpp
)
target_include_directories(loader_local_matching_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
# Guard must match the condition for src/single_instance_manager.cpp in cockatrice/CMakeLists.txt.
if(WITH_CLIENT)
add_executable(
single_instance_manager_test ${CMAKE_SOURCE_DIR}/cockatrice/src/single_instance_manager.cpp
single_instance_manager_test.cpp
)
target_include_directories(single_instance_manager_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
add_test(NAME single_instance_manager_test COMMAND single_instance_manager_test)
endif()
find_package(GTest) find_package(GTest)
if(NOT GTEST_FOUND) if(NOT GTEST_FOUND)
@ -122,91 +30,303 @@ if(NOT GTEST_FOUND)
target_include_directories(gtest INTERFACE "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/gtest-src/include>") target_include_directories(gtest INTERFACE "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/gtest-src/include>")
set(GTEST_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/gtest-src/include") set(GTEST_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/gtest-src/include")
set(GTEST_BOTH_LIBRARIES gtest) # gtest_main is not optional here. FindGTest sets GTEST_BOTH_LIBRARIES to both halves, so this
add_dependencies(dummy_test gtest) # has to match it or the two paths disagree about what provides main(). A test source that
add_dependencies(expression_test gtest) # defines its own main() gets away with the omission; one that does not fails at link with
add_dependencies(clamped_arithmetic_test gtest) # `undefined reference to main` pointing at crt1.o, which names neither gtest nor this line.
add_dependencies(test_age_formatting gtest) set(GTEST_BOTH_LIBRARIES gtest gtest_main)
add_dependencies(password_hash_test gtest)
add_dependencies(playmat_resolver_test gtest)
add_dependencies(deck_hash_performance_test gtest)
add_dependencies(server_card_counter_test gtest)
add_dependencies(server_counter_test gtest)
add_dependencies(server_rate_limiter_test gtest)
add_dependencies(server_developer_role_test gtest)
add_dependencies(server_game_join_test gtest)
add_dependencies(warning_categories_test gtest)
if(TARGET translation_loader_test)
add_dependencies(translation_loader_test gtest)
endif()
add_dependencies(report_categories_test gtest)
add_dependencies(lag_monitor_test gtest)
add_dependencies(latency_tracker_test gtest)
add_dependencies(metrics_registry_test gtest)
add_dependencies(loader_local_matching_test gtest)
add_dependencies(single_instance_manager_test gtest)
endif() endif()
# Directory-scoped on purpose: the test subdirectories below add targets that include the
# fetched gtest headers and do not repeat this path themselves.
include_directories(${GTEST_INCLUDE_DIRS}) include_directories(${GTEST_INCLUDE_DIRS})
target_link_libraries(dummy_test Threads::Threads ${GTEST_BOTH_LIBRARIES})
target_link_libraries(expression_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}) # --- Test registration ----------------------------------------------------------
target_link_libraries( #
clamped_arithmetic_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # Every test target needs the same four steps: build the executable, depend on gtest when it
) # was fetched from source, link the shared test libraries, and hand the cases to CTest. The
target_link_libraries( # `if(NOT GTEST_FOUND)` branch is the easy one to forget — omit it and the link fails with
test_age_formatting libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # undefined gtest symbols — so it lives here once instead of being repeated per test.
) #
target_link_libraries( # This also replaces `add_test(NAME x COMMAND x)`. Naming the binary as a single CTest entry
password_hash_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # hides which case failed and makes `ctest -R Suite.Case` impossible; discovery exposes each
) # TEST() as its own CTest entry instead.
target_link_libraries( #
playmat_resolver_test libcockatrice_deck_list libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} # Labels: exactly one per test, because gtest_discover_tests() cannot carry more than one.
${TEST_QT_MODULES} # GoogleTestAddTests.cmake accumulates the generated script with `foreach(arg ${ARGN})`, so a
) # label list serialises as bare `LABELS ci server` in the CTestTestfile, and CTest reads only
target_link_libraries( # the first value of a property and silently discards the rest. A label therefore classifies a
deck_hash_performance_test libcockatrice_deck_list libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} # test into exactly one group, and the three groups cover every selection worth making:
${TEST_QT_MODULES} #
) # ci the default hermetic set, so `ctest -LE bench` runs everything but benchmarks
target_link_libraries( # server servatrice-facing tests, so `ctest -L server` works
server_card_counter_test libcockatrice_network Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # bench the slow suites, kept out of the default run
) #
target_link_libraries( # A second label is a configure-time FATAL_ERROR rather than a line CTest quietly reads as one.
server_counter_test libcockatrice_network Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # Anything orthogonal to a test's kind belongs in a helper flag beside the label, so it
) # composes with the group instead of competing for the single slot.
target_link_libraries( #
server_rate_limiter_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} # TIMEOUT is bounded per test because CTest's implicit default is 1500s: one hung socket wait
) # would otherwise stall CI for 25 minutes.
target_link_libraries( #
server_developer_role_test libcockatrice_network libcockatrice_rng Threads::Threads ${GTEST_BOTH_LIBRARIES} # EXTRA_LIBS is appended after the shared libraries so a caller adding a static archive (zlib,
${TEST_QT_MODULES} # lzma) keeps it last, which is where the linker needs it.
)
target_link_libraries( function(cockatrice_add_test)
server_game_join_test libcockatrice_network_server_remote libcockatrice_rng Threads::Threads ${GTEST_BOTH_LIBRARIES} cmake_parse_arguments(PARSE_ARGV 0 ARG "MANUAL" "NAME" "SOURCES;LIBS;LABELS;DEFINITIONS;INCLUDE_DIRS;EXTRA_LIBS")
${TEST_QT_MODULES}
) if(NOT ARG_NAME OR NOT ARG_SOURCES)
target_link_libraries( message(FATAL_ERROR "cockatrice_add_test requires at least NAME and SOURCES")
warning_categories_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} endif()
)
if(TARGET translation_loader_test) add_executable(${ARG_NAME} ${ARG_SOURCES})
if(ARG_INCLUDE_DIRS)
target_include_directories(${ARG_NAME} PRIVATE ${ARG_INCLUDE_DIRS})
endif()
if(ARG_DEFINITIONS)
target_compile_definitions(${ARG_NAME} PRIVATE ${ARG_DEFINITIONS})
endif()
target_link_libraries( target_link_libraries(
translation_loader_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ${ARG_NAME} ${ARG_LIBS} Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ${ARG_EXTRA_LIBS}
)
# Only needed when gtest was downloaded and add_subdirectory'd above. An imported gtest
# target already carries its own dependency, so this must stay conditional.
if(NOT GTEST_FOUND)
add_dependencies(${ARG_NAME} gtest gtest_main)
endif()
# MANUAL targets are built but deliberately kept out of ctest: benchmarks that need a card
# database, hit the network, or measure RAM. Leaving them unregistered keeps CI hermetic
# and fast. They still link gtest so they can use TEST() without a second code path.
if(ARG_MANUAL)
return()
endif()
# One label only, per the note above. Rejecting a second loudly beats emitting a
# CTestTestfile line that CTest will quietly read as one label.
list(LENGTH ARG_LABELS _label_count)
if(_label_count GREATER 1)
message(FATAL_ERROR "${ARG_NAME}: pass at most one label, got '${ARG_LABELS}'")
endif()
if(NOT ARG_LABELS)
set(ARG_LABELS ci)
endif()
# GoogleTestAddTests defaults DISCOVERY_TIMEOUT to 5s. A plain debug binary answers
# --gtest_list_tests in 0.04s, but that budget is thin once several binaries discover
# concurrently behind a -j build, and being over it fails at the *link* step with a bare
# "Process terminated due to timeout" that points nowhere near the cause.
gtest_discover_tests(
${ARG_NAME} DISCOVERY_MODE POST_BUILD DISCOVERY_TIMEOUT 60
PROPERTIES LABELS "${ARG_LABELS}"
TIMEOUT 60
)
endfunction()
# Same wiring for targets that are built but deliberately kept out of ctest: benchmarks that
# need a card database, hit the network, or measure RAM. A separate name rather than a MANUAL
# flag spelled out at each call site, so "this is not in the CI suite" is visible in the CMake
# file. Note the unquoted expansions: an unset multi-value keyword expands to zero arguments,
# which is what lets this forward a caller's keywords verbatim without tripping the FATAL_ERROR
# guard above on an empty list.
function(cockatrice_add_manual_test)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "NAME" "SOURCES;LIBS;DEFINITIONS;INCLUDE_DIRS;EXTRA_LIBS")
cockatrice_add_test(
NAME
${ARG_NAME}
SOURCES
${ARG_SOURCES}
LIBS
${ARG_LIBS}
DEFINITIONS
${ARG_DEFINITIONS}
INCLUDE_DIRS
${ARG_INCLUDE_DIRS}
EXTRA_LIBS
${ARG_EXTRA_LIBS}
MANUAL
)
endfunction()
# --- Unit tests ------------------------------------------------------------------
cockatrice_add_test(NAME expression_test SOURCES expression_test.cpp LIBS libcockatrice_utility)
cockatrice_add_test(NAME clamped_arithmetic_test SOURCES clamped_arithmetic_test.cpp LIBS libcockatrice_utility)
cockatrice_add_test(NAME test_age_formatting SOURCES test_age_formatting.cpp LIBS libcockatrice_utility)
cockatrice_add_test(NAME password_hash_test SOURCES password_hash_test.cpp LIBS libcockatrice_utility)
cockatrice_add_test(NAME report_categories_test SOURCES report_categories_test.cpp LIBS libcockatrice_utility)
cockatrice_add_test(NAME warning_categories_test SOURCES warning_categories_test.cpp LIBS libcockatrice_utility)
cockatrice_add_test(
NAME
playmat_resolver_test
SOURCES
playmat_resolver_test.cpp
LIBS
libcockatrice_deck_list
libcockatrice_utility
)
cockatrice_add_test(
NAME
server_rate_limiter_test
SOURCES
server_rate_limiter_test.cpp
LIBS
libcockatrice_utility
LABELS
server
)
cockatrice_add_test(
NAME
server_card_counter_test
SOURCES
server_card_counter_test.cpp
LIBS
libcockatrice_network
LABELS
server
)
cockatrice_add_test(
NAME
server_counter_test
SOURCES
server_counter_test.cpp
LIBS
libcockatrice_network
LABELS
server
)
cockatrice_add_test(
NAME
server_developer_role_test
SOURCES
server_developer_role_test.cpp
LIBS
libcockatrice_network
libcockatrice_rng
LABELS
server
)
cockatrice_add_test(
NAME
server_game_join_test
SOURCES
server_game_join_test.cpp
LIBS
libcockatrice_network_server_remote
libcockatrice_rng
LABELS
server
)
cockatrice_add_test(
NAME
latency_tracker_test
SOURCES
latency_tracker_test.cpp
LIBS
libcockatrice_network
LABELS
server
)
cockatrice_add_test(
NAME
lag_monitor_test
SOURCES
${CMAKE_SOURCE_DIR}/cockatrice/src/client/lag_monitor.cpp
lag_monitor_test.cpp
INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/cockatrice/src
)
cockatrice_add_test(
NAME
metrics_registry_test
SOURCES
${CMAKE_SOURCE_DIR}/servatrice/src/metrics_registry.cpp
metrics_registry_test.cpp
INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/servatrice/src
LABELS
server
)
cockatrice_add_test(
NAME
loader_local_matching_test
SOURCES
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/cache_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/card_counter_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/shortcuts_settings.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp
${VERSION_STRING_CPP}
loader_local_matching_test.cpp
LIBS
libcockatrice_settings
INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/cockatrice/src
)
cockatrice_add_test(
NAME
deck_hash_performance_test
SOURCES
deck_hash_performance_test.cpp
LIBS
libcockatrice_deck_list
libcockatrice_utility
LABELS
bench
)
# The translation loader test compiles a .qm fixture, which needs lrelease from Qt Linguist.
if(TARGET Qt6::lrelease)
set(TRANSLATION_LOADER_TEST_QM "${CMAKE_CURRENT_BINARY_DIR}/translation_loader_test_de.qm")
add_custom_command(
OUTPUT "${TRANSLATION_LOADER_TEST_QM}"
COMMAND Qt6::lrelease "${CMAKE_CURRENT_SOURCE_DIR}/translation_loader_test.ts" -qm "${TRANSLATION_LOADER_TEST_QM}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/translation_loader_test.ts"
COMMENT "Compiling translation_loader_test.ts"
)
add_custom_target(translation_loader_test_qm DEPENDS "${TRANSLATION_LOADER_TEST_QM}")
cockatrice_add_test(
NAME
translation_loader_test
SOURCES
translation_loader_test.cpp
LIBS
libcockatrice_utility
DEFINITIONS
TRANSLATION_LOADER_TEST_DIR="${CMAKE_CURRENT_BINARY_DIR}"
)
add_dependencies(translation_loader_test translation_loader_test_qm)
# A multi-config generator (MSBuild, Xcode) puts the executable in a per-config subdirectory while
# the .qm stays in the current binary directory, so copy the fixture next to the binary: that is the
# layout ABuildTreeFindsTheTranslationsNextToTheExecutable is about, and the only one it finds on
# those generators.
add_custom_command(
TARGET translation_loader_test
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${TRANSLATION_LOADER_TEST_QM}"
"$<TARGET_FILE_DIR:translation_loader_test>/"
VERBATIM
) )
endif() endif()
target_link_libraries(
report_categories_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
target_link_libraries(lag_monitor_test Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES})
target_link_libraries(
latency_tracker_test libcockatrice_network Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
target_include_directories(metrics_registry_test PRIVATE ${CMAKE_SOURCE_DIR}/servatrice/src)
target_link_libraries(metrics_registry_test ${TEST_QT_MODULES} Threads::Threads ${GTEST_BOTH_LIBRARIES})
target_link_libraries(
loader_local_matching_test libcockatrice_settings Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
# Guard must match the condition for src/single_instance_manager.cpp in cockatrice/CMakeLists.txt.
if(WITH_CLIENT) if(WITH_CLIENT)
target_link_libraries(single_instance_manager_test Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}) cockatrice_add_test(
NAME
single_instance_manager_test
SOURCES
${CMAKE_SOURCE_DIR}/cockatrice/src/single_instance_manager.cpp
single_instance_manager_test.cpp
INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/cockatrice/src
)
endif() endif()
add_subdirectory(card_zone_algorithms) add_subdirectory(card_zone_algorithms)

View file

@ -1,15 +1,4 @@
add_executable(card_zone_algorithms_test card_zone_algorithms_test.cpp) cockatrice_add_test(
NAME card_zone_algorithms_test SOURCES card_zone_algorithms_test.cpp INCLUDE_DIRS
target_include_directories(card_zone_algorithms_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src/game/zones) ${CMAKE_SOURCE_DIR}/cockatrice/src/game/zones
target_link_libraries(
card_zone_algorithms_test
PRIVATE Threads::Threads
PRIVATE ${GTEST_BOTH_LIBRARIES}
) )
add_test(NAME card_zone_algorithms_test COMMAND card_zone_algorithms_test)
if(NOT GTEST_FOUND)
add_dependencies(card_zone_algorithms_test gtest)
endif()

View file

@ -9,61 +9,46 @@ add_definitions("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"")
# ------------------------ # ------------------------
# Card Database Test # Card Database Test
# ------------------------ # ------------------------
add_executable(carddatabase_test ${MOCKS_SOURCES} ${VERSION_STRING_CPP} carddatabase_test.cpp mocks.cpp) cockatrice_add_test(
NAME
target_link_libraries(
carddatabase_test carddatabase_test
PRIVATE libcockatrice_card SOURCES
PRIVATE Threads::Threads ${VERSION_STRING_CPP}
PRIVATE ${GTEST_BOTH_LIBRARIES} carddatabase_test.cpp
PRIVATE ${TEST_QT_MODULES} mocks.cpp
LIBS
libcockatrice_card
) )
add_test(NAME carddatabase_test COMMAND carddatabase_test)
# ------------------------
# Load Benchmark (manual, not run in CI)
# ------------------------
add_executable(load_benchmark ${MOCKS_SOURCES} ${VERSION_STRING_CPP} load_benchmark.cpp mocks.cpp)
target_link_libraries(
load_benchmark
PRIVATE libcockatrice_card
PRIVATE libcockatrice_models
PRIVATE Threads::Threads
PRIVATE ${GTEST_BOTH_LIBRARIES}
PRIVATE ${TEST_QT_MODULES}
)
if(NOT GTEST_FOUND)
add_dependencies(load_benchmark gtest)
endif()
# ------------------------ # ------------------------
# Filter String Test # Filter String Test
# (guard must match the condition for libcockatrice_filters in the root CMakeLists.txt) # (guard must match the condition for libcockatrice_filters in the root CMakeLists.txt)
# ------------------------ # ------------------------
if(WITH_ORACLE OR WITH_CLIENT) if(WITH_ORACLE OR WITH_CLIENT)
add_executable(filter_string_test ${MOCKS_SOURCES} ${VERSION_STRING_CPP} filter_string_test.cpp mocks.cpp) cockatrice_add_test(
NAME
target_link_libraries(
filter_string_test filter_string_test
PRIVATE libcockatrice_filters SOURCES
PRIVATE Threads::Threads ${VERSION_STRING_CPP}
PRIVATE ${GTEST_BOTH_LIBRARIES} filter_string_test.cpp
PRIVATE ${TEST_QT_MODULES} mocks.cpp
LIBS
libcockatrice_filters
) )
add_test(NAME filter_string_test COMMAND filter_string_test)
if(NOT GTEST_FOUND)
add_dependencies(filter_string_test gtest)
endif()
endif() endif()
# ------------------------ # ------------------------
# Dependencies on gtest # Load Benchmark (manual, not run in CI)
# ------------------------ # ------------------------
if(NOT GTEST_FOUND) cockatrice_add_manual_test(
add_dependencies(carddatabase_test gtest) NAME
endif() load_benchmark
SOURCES
${VERSION_STRING_CPP}
load_benchmark.cpp
mocks.cpp
LIBS
libcockatrice_card
libcockatrice_models
MANUAL
)

View file

@ -1,33 +1,23 @@
add_executable(deck_list_model_custom_zones_test ${VERSION_STRING_CPP} deck_list_model_custom_zones_test.cpp) cockatrice_add_test(
NAME
if(NOT GTEST_FOUND)
add_dependencies(deck_list_model_custom_zones_test gtest)
endif()
target_link_libraries(
deck_list_model_custom_zones_test deck_list_model_custom_zones_test
SOURCES
${VERSION_STRING_CPP}
deck_list_model_custom_zones_test.cpp
LIBS
libcockatrice_models libcockatrice_models
libcockatrice_card libcockatrice_card
libcockatrice_deck_list libcockatrice_deck_list
Threads::Threads
${GTEST_BOTH_LIBRARIES}
${TEST_QT_MODULES}
) )
add_test(NAME deck_list_model_custom_zones_test COMMAND deck_list_model_custom_zones_test)
add_executable(deck_list_model_zone_integration_test ${VERSION_STRING_CPP} deck_list_model_zone_integration_test.cpp) cockatrice_add_test(
NAME
if(NOT GTEST_FOUND)
add_dependencies(deck_list_model_zone_integration_test gtest)
endif()
target_link_libraries(
deck_list_model_zone_integration_test deck_list_model_zone_integration_test
SOURCES
${VERSION_STRING_CPP}
deck_list_model_zone_integration_test.cpp
LIBS
libcockatrice_models libcockatrice_models
libcockatrice_card libcockatrice_card
libcockatrice_deck_list libcockatrice_deck_list
Threads::Threads
${GTEST_BOTH_LIBRARIES}
${TEST_QT_MODULES}
) )
add_test(NAME deck_list_model_zone_integration_test COMMAND deck_list_model_zone_integration_test)

View file

@ -1,10 +1 @@
add_executable(deck_list_zones_test deck_list_zones_test.cpp) cockatrice_add_test(NAME deck_list_zones_test SOURCES deck_list_zones_test.cpp LIBS libcockatrice_deck_list)
if(NOT GTEST_FOUND)
add_dependencies(deck_list_zones_test gtest)
endif()
target_link_libraries(
deck_list_zones_test libcockatrice_deck_list Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
add_test(NAME deck_list_zones_test COMMAND deck_list_zones_test)

View file

@ -1,19 +0,0 @@
#include "gtest/gtest.h"
namespace
{
class FooTest : public ::testing::Test
{
};
TEST(DummyTest, Works)
{
ASSERT_EQ(1, 1) << "One is not equal to one";
}
} // namespace
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -1,12 +1,13 @@
add_definitions("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"") add_definitions("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"")
add_executable(loading_from_clipboard_test ${VERSION_STRING_CPP} clipboard_testing.cpp loading_from_clipboard_test.cpp)
if(NOT GTEST_FOUND) cockatrice_add_test(
add_dependencies(loading_from_clipboard_test gtest) NAME
endif() loading_from_clipboard_test
SOURCES
target_link_libraries( ${VERSION_STRING_CPP}
loading_from_clipboard_test libcockatrice_deck_list libcockatrice_card Threads::Threads ${GTEST_BOTH_LIBRARIES} clipboard_testing.cpp
${TEST_QT_MODULES} loading_from_clipboard_test.cpp
LIBS
libcockatrice_deck_list
libcockatrice_card
) )
add_test(NAME loading_from_clipboard_test COMMAND loading_from_clipboard_test)

View file

@ -1,16 +1,11 @@
add_executable(reverse_card_move_test reverse_card_move_test.cpp) cockatrice_add_test(
NAME
if(NOT GTEST_FOUND)
add_dependencies(reverse_card_move_test gtest)
endif()
target_link_libraries(
reverse_card_move_test reverse_card_move_test
PRIVATE libcockatrice_network_server_remote SOURCES
PRIVATE libcockatrice_rng reverse_card_move_test.cpp
PRIVATE Threads::Threads LIBS
PRIVATE ${GTEST_BOTH_LIBRARIES} libcockatrice_network_server_remote
PRIVATE ${TEST_QT_MODULES} libcockatrice_rng
LABELS
server
) )
add_test(NAME reverse_card_move_test COMMAND reverse_card_move_test)

View file

@ -1,33 +1,26 @@
add_executable(parse_cipt_test ../../oracle/src/parsehelpers.cpp parse_cipt_test.cpp) cockatrice_add_test(NAME parse_cipt_test SOURCES ../../oracle/src/parsehelpers.cpp parse_cipt_test.cpp)
if(NOT GTEST_FOUND)
add_dependencies(parse_cipt_test gtest)
endif()
target_link_libraries(parse_cipt_test Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES})
add_test(NAME parse_cipt_test COMMAND parse_cipt_test)
# Oracle importer unit tests # Oracle importer unit tests
add_executable( cockatrice_add_test(
oracle_importer_test ${VERSION_STRING_CPP} ../../oracle/src/oracleimporter.cpp ../../oracle/src/parsehelpers.cpp NAME
../../oracle/src/raw_json_scanner.cpp oracle_importer_test.cpp oracle_importer_test
SOURCES
${VERSION_STRING_CPP}
../../oracle/src/oracleimporter.cpp
../../oracle/src/parsehelpers.cpp
../../oracle/src/raw_json_scanner.cpp
oracle_importer_test.cpp
LIBS
libcockatrice_card
libcockatrice_interfaces
) )
if(NOT GTEST_FOUND)
add_dependencies(oracle_importer_test gtest)
endif()
target_link_libraries(
oracle_importer_test libcockatrice_card libcockatrice_interfaces Threads::Threads ${GTEST_BOTH_LIBRARIES}
${TEST_QT_MODULES}
)
add_test(NAME oracle_importer_test COMMAND oracle_importer_test)
# Oracle importer benchmark tests (manual, not run in CI, incl. RAM benchmark) # Oracle importer benchmark tests (manual, not run in CI, incl. RAM benchmark)
# Optional compression libs, mirrored from oracle/CMakeLists.txt, so the benchmark # Optional compression libs, mirrored from oracle/CMakeLists.txt, so the benchmark
# can download and decompress whatever AllPrintings format the default URL selects. # can download and decompress whatever AllPrintings format the default URL selects.
# add_definitions() is directory-scoped and order-independent, so HAS_ZLIB/HAS_LZMA also
# reach the two unit tests above. That is harmless: those macros gate code only in
# oracle/src/pages.cpp and oracle/src/pagetemplates.cpp, which no test target compiles.
find_package(ZLIB) find_package(ZLIB)
if(ZLIB_FOUND) if(ZLIB_FOUND)
add_definitions("-DHAS_ZLIB") add_definitions("-DHAS_ZLIB")
@ -48,22 +41,20 @@ else()
message(STATUS "Oracle tests: LibLZMA not found; xz download benchmark disabled") message(STATUS "Oracle tests: LibLZMA not found; xz download benchmark disabled")
endif() endif()
add_executable( cockatrice_add_manual_test(
oracle_importer_benchmark_test NAME
${VERSION_STRING_CPP} ../../oracle/src/oracleimporter.cpp ../../oracle/src/parsehelpers.cpp
../../oracle/src/raw_json_scanner.cpp oracle_importer_benchmark_test.cpp ${_ORACLE_BENCH_EXTRA_SOURCES}
)
if(NOT GTEST_FOUND)
add_dependencies(oracle_importer_benchmark_test gtest)
endif()
target_link_libraries(
oracle_importer_benchmark_test oracle_importer_benchmark_test
SOURCES
${VERSION_STRING_CPP}
../../oracle/src/oracleimporter.cpp
../../oracle/src/parsehelpers.cpp
../../oracle/src/raw_json_scanner.cpp
oracle_importer_benchmark_test.cpp
${_ORACLE_BENCH_EXTRA_SOURCES}
LIBS
libcockatrice_card libcockatrice_card
libcockatrice_interfaces libcockatrice_interfaces
Threads::Threads EXTRA_LIBS
${GTEST_BOTH_LIBRARIES}
${TEST_QT_MODULES}
${_ORACLE_BENCH_EXTRA_LIBRARIES} ${_ORACLE_BENCH_EXTRA_LIBRARIES}
MANUAL
) )

View file

@ -1,8 +1,10 @@
# Manual benchmark hitting the real card image hosts. Not registered with # Manual benchmark hitting the real card image hosts. Not registered with CTest: it requires a
# add_test(): it requires a cards.xml, touches the network for minutes at a # cards.xml, touches the network for minutes at a time, and needs network access. Build it
# time, and needs network access. Build it explicitly and run by hand. # explicitly and run by hand.
add_executable( cockatrice_add_manual_test(
NAME
picture_loader_benchmark_test picture_loader_benchmark_test
SOURCES
${VERSION_STRING_CPP} ${VERSION_STRING_CPP}
../../cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp ../../cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp
../../cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp ../../cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp
@ -11,16 +13,12 @@ add_executable(
../../cockatrice/src/client/settings/cache_settings.h ../../cockatrice/src/client/settings/cache_settings.h
picture_loader_benchmark.cpp picture_loader_benchmark.cpp
settings_cache_mock.cpp settings_cache_mock.cpp
) LIBS
target_include_directories(picture_loader_benchmark_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
target_link_libraries(
picture_loader_benchmark_test
libcockatrice_card libcockatrice_card
libcockatrice_settings libcockatrice_settings
libcockatrice_interfaces libcockatrice_interfaces
libcockatrice_utility libcockatrice_utility
Threads::Threads INCLUDE_DIRS
${TEST_QT_MODULES} ${CMAKE_SOURCE_DIR}/cockatrice/src
MANUAL
) )

View file

@ -1,26 +1,14 @@
add_executable(settings_manager_test settings_manager_test.cpp) cockatrice_add_test(NAME settings_manager_test SOURCES settings_manager_test.cpp LIBS libcockatrice_settings)
add_executable(settings_defaults_test settings_defaults_test.cpp)
add_executable(settings_migration_test settings_migration_test.cpp)
target_link_libraries( cockatrice_add_test(
settings_manager_test libcockatrice_settings Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} NAME
settings_defaults_test
SOURCES
settings_defaults_test.cpp
LIBS
libcockatrice_settings
DEFINITIONS
SETTINGS_UNIT_TEST
) )
target_link_libraries( cockatrice_add_test(NAME settings_migration_test SOURCES settings_migration_test.cpp LIBS libcockatrice_settings)
settings_defaults_test libcockatrice_settings Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
target_compile_definitions(settings_defaults_test PRIVATE SETTINGS_UNIT_TEST)
target_link_libraries(
settings_migration_test libcockatrice_settings Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
)
add_test(NAME settings_manager_test COMMAND settings_manager_test)
add_test(NAME settings_defaults_test COMMAND settings_defaults_test)
add_test(NAME settings_migration_test COMMAND settings_migration_test)
if(NOT GTEST_FOUND)
add_dependencies(settings_manager_test gtest)
add_dependencies(settings_defaults_test gtest)
add_dependencies(settings_migration_test gtest)
endif()

View file

@ -1,5 +1,7 @@
add_executable( cockatrice_add_test(
NAME
theme_migration_test theme_migration_test
SOURCES
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_manager.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_manager.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_config.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_config.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/pixel_map_generator.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/pixel_map_generator.cpp
@ -9,22 +11,11 @@ add_executable(
${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp
${VERSION_STRING_CPP} ${VERSION_STRING_CPP}
theme_migration_test.cpp theme_migration_test.cpp
) LIBS
target_include_directories(theme_migration_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
target_link_libraries(
theme_migration_test
libcockatrice_settings libcockatrice_settings
libcockatrice_network libcockatrice_network
libcockatrice_network_server_remote libcockatrice_network_server_remote
libcockatrice_protocol libcockatrice_protocol
Threads::Threads INCLUDE_DIRS
${GTEST_BOTH_LIBRARIES} ${CMAKE_SOURCE_DIR}/cockatrice/src
${TEST_QT_MODULES}
) )
add_test(NAME theme_migration_test COMMAND theme_migration_test)
if(NOT GTEST_FOUND)
add_dependencies(theme_migration_test gtest)
endif()