From fec693ca2a8274054eb9fb1518dd878eb6cdc148 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:21:40 +0200 Subject: [PATCH] [Tests] Scope loader matcher settings to the process to fix parallel-run flakes (#7504) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Tests] Scope loader matcher settings to the process to fix parallel-run flakes * [Tests] Clean up per-process settings sandbox after loader matcher run * [Tests] Skip loader matcher sandbox cleanup during gtest discovery --------- Co-authored-by: Lukas Brübach --- tests/loader_local_matching_test.cpp | 38 +++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/loader_local_matching_test.cpp b/tests/loader_local_matching_test.cpp index 13d3e5bb3..7632e60d4 100644 --- a/tests/loader_local_matching_test.cpp +++ b/tests/loader_local_matching_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -223,8 +224,43 @@ int main(int argc, char **argv) } QCoreApplication app(argc, argv); + + // Every TEST() runs as its own process and CI runs them in parallel (ctest -j4), + // while the picture paths round-trip through the process-global SettingsCache + // file. Parallel cases must therefore never share one settings directory: on + // platforms where QStandardPaths ignores the $HOME override above (macOS + // resolves the home directory via system APIs), every case would otherwise read + // and write the same paths.ini, and a sibling's setPicsPath can land between our + // own set and the loader's get — so the loader searches a foreign (or empty) + // directory and flakily returns a null image. Scope the settings to this process + // with a pid-unique application name; PIDs are never reused by live processes. + QCoreApplication::setOrganizationName(QStringLiteral("CockatriceTest")); + QCoreApplication::setApplicationName( + QStringLiteral("loader-local-matching-test-%1").arg(QCoreApplication::applicationPid())); + QLoggingCategory::setFilterRules("card_picture_loader.*=false\nsettings_cache.*=false"); ::testing::InitGoogleTest(&argc, argv); + + // CMake's gtest discovery runs this binary with --gtest_list_tests, which lists + // without running any test body. Arming the cleanup guard here would make it the + // sole SettingsCache::instance() call in that mode, instantiating the + // Q_GLOBAL_STATIC singleton (and its QNetworkAccessManagers) just to tear down at + // exit — which LeakSanitizer reports as leaks and fails discovery on the sanitizer + // leg. Skip the sandbox cleanup entirely when only listing. + if (::testing::GTEST_FLAG(list_tests)) { + return RUN_ALL_TESTS(); + } + + // Best-effort cleanup of this process's settings sandbox. QStandardPaths test + // mode is never auto-cleaned, and on macOS the $HOME override above is ignored, + // so without this every run litters ~/.qttest with one pid-unique directory. + // Safe under parallel runs: the pid-unique application name above guarantees + // this directory belongs to this process alone. + const auto cleanupSandbox = qScopeGuard([] { + QDir(SettingsCache::instance().getDataPath()).removeRecursively(); + QDir(SettingsCache::instance().getCachePath()).removeRecursively(); + }); + return RUN_ALL_TESTS(); -} \ No newline at end of file +}