From ac2ec118e90d1547fa9666642119d25b8f2397ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 11 Sep 2026 17:47:42 +0200 Subject: [PATCH] test: Register EEST fixtures as ctest tests per directory The execution-spec-test suites run as a single `evmone test` invocation over the whole fixture tree, so they execute serially on one core. Add EVMONE_SPEC_TESTS, a list of base directories scanned at configure time: the fixture directories three levels under state_tests / blockchain_tests become one ctest test each, labelled by type and named by the path relative to the base. A tree shallower than that is registered at its leaves, so every fixture runs exactly once. Empty by default, so normal builds register nothing. Registering each file instead is slower than the serial run it replaces, because ctest pays its per-test cost on one thread whatever --parallel says. Per directory it is up to ~4x faster on four cores. --- test/CMakeLists.txt | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c56bf1526f..bbc9f7f63a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -72,3 +72,53 @@ set_target_properties( LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} ) + +# Register execution-spec-test (EEST) fixtures as ctest tests so they run in parallel +# under `ctest --parallel` instead of one serial runner invocation. EVMONE_SPEC_TESTS is a +# list of base directories; below each, the fixture directories three levels under +# `state_tests` / `blockchain_tests` become one test each, running `evmone test` over the +# directory. A tree shallower than that is registered at its leaves, so every fixture runs +# exactly once: no fixture directory holds both files and subdirectories. +# +# Grouping by directory rather than by file is what makes this a win: ctest's per-test cost +# is paid on one thread whatever --parallel says, so registering every file made the run +# slower than the serial one it replaces. +# +# Tests are named by the directory path relative to the base, so fixtures from different +# sources stay distinct. The fixtures must exist at configure time. Select a type with +# `ctest -L state_tests`, a source with `ctest -R `. +set(EVMONE_SPEC_TESTS "" CACHE STRING + "List of base directories scanned for execution-spec-test fixtures to register as ctest tests") + +function(evmone_register_spec_test_dir base dir type depth) + file(GLOB entries LIST_DIRECTORIES true "${dir}/*") + set(subdirs "") + foreach(entry ${entries}) + if(IS_DIRECTORY "${entry}") + list(APPEND subdirs "${entry}") + endif() + endforeach() + + # Three levels down, or a leaf above it, is one test. Otherwise recurse. + if(depth LESS 3 AND subdirs) + foreach(subdir ${subdirs}) + math(EXPR next "${depth} + 1") + evmone_register_spec_test_dir("${base}" "${subdir}" "${type}" ${next}) + endforeach() + return() + endif() + + file(RELATIVE_PATH name "${base}" "${dir}") + add_test(NAME "${name}" COMMAND evmone-cli test "${dir}") + # Per-process profraw so parallel coverage runs do not clobber each other. + set_tests_properties("${name}" PROPERTIES LABELS "${type}" + ENVIRONMENT "LLVM_PROFILE_FILE=${PROJECT_BINARY_DIR}/${type}-%m.profraw") +endfunction() + +foreach(base ${EVMONE_SPEC_TESTS}) + foreach(type state_tests blockchain_tests) + if(IS_DIRECTORY "${base}/fixtures/${type}") + evmone_register_spec_test_dir("${base}" "${base}/fixtures/${type}" "${type}" 0) + endif() + endforeach() +endforeach()