[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.
This commit is contained in:
Lukas Brübach 2026-10-05 09:48:22 +02:00
parent 5ff88c1cf3
commit 5aafeffe4c

View file

@ -48,10 +48,19 @@ include_directories(${GTEST_INCLUDE_DIRS})
# hides which case failed and makes `ctest -R Suite.Case` impossible; discovery exposes each # hides which case failed and makes `ctest -R Suite.Case` impossible; discovery exposes each
# TEST() as its own CTest entry instead. # TEST() as its own CTest entry instead.
# #
# Labels: `ci` is applied to every registered test and marks the default CI run, so # Labels: exactly one per test, because gtest_discover_tests() cannot carry more than one.
# `ctest -LE bench` is the fast hermetic set. Add `gui` for a test that constructs a # GoogleTestAddTests.cmake accumulates the generated script with `foreach(arg ${ARGN})`, so a
# QApplication (none do today — CI has no display), `server` for servatrice-facing tests # label list serialises as bare `LABELS ci server` in the CTestTestfile, and CTest reads only
# so `ctest -L server` works, `bench` for the slow suites. # the first value of a property and silently discards the rest. A label therefore classifies a
# test into exactly one group, and the three groups cover every selection worth making:
#
# ci the default hermetic set, so `ctest -LE bench` runs everything but benchmarks
# server servatrice-facing tests, so `ctest -L server` works
# bench the slow suites, kept out of the default run
#
# A second label is a configure-time FATAL_ERROR rather than a line CTest quietly reads as one.
# 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.
# #
# TIMEOUT is bounded per test because CTest's implicit default is 1500s: one hung socket wait # TIMEOUT is bounded per test because CTest's implicit default is 1500s: one hung socket wait
# would otherwise stall CI for 25 minutes. # would otherwise stall CI for 25 minutes.
@ -93,14 +102,22 @@ function(cockatrice_add_test)
return() return()
endif() 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) if(NOT ARG_LABELS)
set(ARG_LABELS ci) set(ARG_LABELS ci)
else()
list(APPEND ARG_LABELS ci)
endif() 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( gtest_discover_tests(
${ARG_NAME} DISCOVERY_MODE POST_BUILD ${ARG_NAME} DISCOVERY_MODE POST_BUILD DISCOVERY_TIMEOUT 60
PROPERTIES LABELS "${ARG_LABELS}" PROPERTIES LABELS "${ARG_LABELS}"
TIMEOUT 60 TIMEOUT 60
) )