[Lldb-commits] [lldb] [llvm] [lit] Move maxIndividualTestTime from global to test suite config (PR #199996)
Vitaly Buka via lldb-commits
lldb-commits at lists.llvm.org
Wed May 27 07:40:28 PDT 2026
https://github.com/vitalybuka created https://github.com/llvm/llvm-project/pull/199996
Simplify LitConfig initialization and setter to allow None values.
TestingConfig.maxIndividualTestTime is initialized to 0 (or resolved to
0 if None) strictly during initialization.
This fixes an issue where the aggressive BOLT timeout of 60s (previously
set globally on lit_config) was leaking and affecting libc++ tests. By
moving the timeout configuration from the global lit_config to the
individual test suite config, we ensure that timeouts are isolated and
respect suite-local settings without leaking.
PR Stack:
* ➤ https://github.com/llvm/llvm-project/pull/198192
* https://github.com/llvm/llvm-project/pull/198193
Assisted-by: Gemini
>From 632e25f8313033a141e25f788ded9c4154a782f0 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Tue, 26 May 2026 22:26:51 -0700
Subject: [PATCH] [lit] Move maxIndividualTestTime from global to test suite
config
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Simplify LitConfig initialization and setter to allow None values.
TestingConfig.maxIndividualTestTime is initialized to 0 (or resolved to
0 if None) strictly during initialization.
This fixes an issue where the aggressive BOLT timeout of 60s (previously
set globally on lit_config) was leaking and affecting libc++ tests. By
moving the timeout configuration from the global lit_config to the
individual test suite config, we ensure that timeouts are isolated and
respect suite-local settings without leaking.
PR Stack:
* ➤ https://github.com/llvm/llvm-project/pull/198192
* https://github.com/llvm/llvm-project/pull/198193
Assisted-by: Gemini
---
bolt/test/lit.cfg.py | 2 +-
libsycl/test/lit.cfg.py | 2 +-
lldb/test/API/lit.cfg.py | 2 +-
lldb/test/Shell/lit.cfg.py | 2 +-
llvm/utils/lit/lit/LitConfig.py | 5 ++++-
llvm/utils/lit/lit/TestRunner.py | 8 ++++----
llvm/utils/lit/lit/TestingConfig.py | 16 ++++++++++++++++
llvm/utils/lit/lit/formats/googletest.py | 4 ++--
llvm/utils/lit/lit/main.py | 13 +------------
.../lit/tests/Inputs/googletest-timeout/lit.cfg | 2 +-
.../lit/tests/Inputs/shtest-timeout/lit.cfg | 2 +-
11 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/bolt/test/lit.cfg.py b/bolt/test/lit.cfg.py
index 3299051db4983..a3a49444156b2 100644
--- a/bolt/test/lit.cfg.py
+++ b/bolt/test/lit.cfg.py
@@ -69,7 +69,7 @@
supported, errormsg = lit_config.maxIndividualTestTimeIsSupported
if supported:
config.available_features.add("lit-max-individual-test-time")
- lit_config.maxIndividualTestTime = 60
+ config.maxIndividualTestTime = 60
else:
lit_config.warning(
"Setting a timeout per test not supported. "
diff --git a/libsycl/test/lit.cfg.py b/libsycl/test/lit.cfg.py
index 377be90791ef0..2610f23ba90a8 100644
--- a/libsycl/test/lit.cfg.py
+++ b/libsycl/test/lit.cfg.py
@@ -205,7 +205,7 @@ def __exit__(self, exc_type, exc_value, exc_traceback):
import psutil
# Set timeout for a single test
- lit_config.maxIndividualTestTime = 600
+ config.maxIndividualTestTime = 600
except ImportError:
pass
diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py
index 359d45a0c724e..2662a77199641 100644
--- a/lldb/test/API/lit.cfg.py
+++ b/lldb/test/API/lit.cfg.py
@@ -199,7 +199,7 @@ def delete_module_cache(path):
# lit complains if the value is set but it is not supported.
supported, errormsg = lit_config.maxIndividualTestTimeIsSupported
if supported:
- lit_config.maxIndividualTestTime = 600
+ config.maxIndividualTestTime = 600
else:
lit_config.warning("Could not set a default per-test timeout. " + errormsg)
diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py
index 3bff8b087c5a4..1b7532d12ce4a 100644
--- a/lldb/test/Shell/lit.cfg.py
+++ b/lldb/test/Shell/lit.cfg.py
@@ -120,7 +120,7 @@ def calculate_arch_features(arch_string):
# lit complains if the value is set but it is not supported.
supported, errormsg = lit_config.maxIndividualTestTimeIsSupported
if supported:
- lit_config.maxIndividualTestTime = 600
+ config.maxIndividualTestTime = 600
else:
lit_config.warning("Could not set a default per-test timeout. " + errormsg)
diff --git a/llvm/utils/lit/lit/LitConfig.py b/llvm/utils/lit/lit/LitConfig.py
index be8596f0ccdc4..4696a0fda1243 100644
--- a/llvm/utils/lit/lit/LitConfig.py
+++ b/llvm/utils/lit/lit/LitConfig.py
@@ -35,7 +35,7 @@ def __init__(
order,
params,
config_prefix=None,
- maxIndividualTestTime=0,
+ maxIndividualTestTime=None,
maxRetriesPerTest=None,
parallelism_groups={},
per_test_coverage=False,
@@ -123,6 +123,9 @@ def maxIndividualTestTime(self, value):
Interface for setting maximum time to spend executing
a single test
"""
+ if value is None:
+ self._maxIndividualTestTime = None
+ return
if not isinstance(value, int):
self.fatal("maxIndividualTestTime must set to a value of type int.")
self._maxIndividualTestTime = value
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 0159028f36723..66450f5fa6b81 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -703,7 +703,7 @@ def executeScriptInternal(
shenv.env["LIT_CURRENT_TESTCASE"] = test.getFullName()
exitCode, timeoutInfo = executeShCmd(
- cmd, shenv, results, timeout=litConfig.maxIndividualTestTime
+ cmd, shenv, results, timeout=test.config.maxIndividualTestTime
)
out = err = ""
@@ -747,7 +747,7 @@ def executeScriptInternal(
# If nothing interesting happened, move on.
if (
- litConfig.maxIndividualTestTime == 0
+ test.config.maxIndividualTestTime == 0
and result.exitCode == 0
and not result.stdout.strip()
and not result.stderr.strip()
@@ -776,7 +776,7 @@ def executeScriptInternal(
else:
codeStr = str(result.exitCode)
out += "# error: command failed with exit status: %s\n" % (codeStr,)
- if litConfig.maxIndividualTestTime > 0 and result.timeoutReached:
+ if test.config.maxIndividualTestTime > 0 and result.timeoutReached:
out += "# error: command reached timeout: %s\n" % (
str(result.timeoutReached),
)
@@ -900,7 +900,7 @@ def executeScript(
command,
cwd=cwd,
env=env,
- timeout=litConfig.maxIndividualTestTime,
+ timeout=test.config.maxIndividualTestTime,
)
return (out, err, exitCode, None, None)
except lit.util.ExecuteCommandTimeoutException as e:
diff --git a/llvm/utils/lit/lit/TestingConfig.py b/llvm/utils/lit/lit/TestingConfig.py
index a6b4fa212ae35..7c7d51ddaf48d 100644
--- a/llvm/utils/lit/lit/TestingConfig.py
+++ b/llvm/utils/lit/lit/TestingConfig.py
@@ -125,6 +125,7 @@ def fromdefaults(litConfig):
available_features=available_features,
pipefail=True,
standalone_tests=False,
+ maxIndividualTestTime=litConfig.maxIndividualTestTime,
)
def load_from_path(self, path, litConfig):
@@ -185,6 +186,7 @@ def __init__(
is_early=False,
parallelism_group=None,
standalone_tests=False,
+ maxIndividualTestTime=0,
):
self.parent = parent
self.name = str(name)
@@ -199,6 +201,7 @@ def __init__(
self.available_features = set(available_features)
self.pipefail = pipefail
self.standalone_tests = standalone_tests
+ self.maxIndividualTestTime = maxIndividualTestTime or 0
# This list is used by TestRunner.py to restrict running only tests that
# require one of the features in this list if this list is non-empty.
# Configurations can set this list to restrict the set of tests to run.
@@ -247,6 +250,19 @@ def finish(self, litConfig):
and getattr(self, "test_retry_attempts", None) is None
):
self.test_retry_attempts = litConfig.maxRetriesPerTest
+ # Global config is from LIT_OPTS and must override site-specific settings.
+ if litConfig.maxIndividualTestTime is not None:
+ suite_timeout = self.maxIndividualTestTime
+ if suite_timeout > 0 and suite_timeout != litConfig.maxIndividualTestTime:
+ litConfig.note(
+ (
+ "The test suite {0!r} configuration requested an individual"
+ " test timeout of {1} seconds but a timeout of {2} seconds was"
+ " requested on the command line. Forcing timeout to be {2}"
+ " seconds."
+ ).format(self.name, suite_timeout, litConfig.maxIndividualTestTime)
+ )
+ self.maxIndividualTestTime = litConfig.maxIndividualTestTime
@property
def root(self):
diff --git a/llvm/utils/lit/lit/formats/googletest.py b/llvm/utils/lit/lit/formats/googletest.py
index 5d60da509bdb7..e567cce541beb 100644
--- a/llvm/utils/lit/lit/formats/googletest.py
+++ b/llvm/utils/lit/lit/formats/googletest.py
@@ -191,7 +191,7 @@ def get_shard_header(shard_env):
out, _, exitCode = lit.util.executeCommand(
cmd,
env=test.config.environment,
- timeout=litConfig.maxIndividualTestTime,
+ timeout=test.config.maxIndividualTestTime,
redirect_stderr=True,
)
except lit.util.ExecuteCommandTimeoutException as e:
@@ -199,7 +199,7 @@ def get_shard_header(shard_env):
return (
lit.Test.TIMEOUT,
f"{shard_header}{stream_msg}Reached "
- f"timeout of {litConfig.maxIndividualTestTime} seconds",
+ f"timeout of {test.config.maxIndividualTestTime} seconds",
)
if not os.path.exists(test.gtest_json_file):
diff --git a/llvm/utils/lit/lit/main.py b/llvm/utils/lit/lit/main.py
index d1e16b28bea26..a3bd153040a69 100755
--- a/llvm/utils/lit/lit/main.py
+++ b/llvm/utils/lit/lit/main.py
@@ -44,6 +44,7 @@ def main(builtin_params={}):
gtest_sharding=opts.gtest_sharding,
maxRetriesPerTest=opts.maxRetriesPerTest,
update_tests=opts.update_tests,
+ maxIndividualTestTime=opts.maxIndividualTestTime,
)
discovered_tests = lit.discovery.find_tests_for_inputs(
@@ -68,18 +69,6 @@ def main(builtin_params={}):
print(" ".join(sorted(features)))
sys.exit(0)
- # Command line overrides configuration for maxIndividualTestTime.
- if opts.maxIndividualTestTime is not None: # `not None` is important (default: 0)
- if opts.maxIndividualTestTime != lit_config.maxIndividualTestTime:
- lit_config.note(
- (
- "The test suite configuration requested an individual"
- " test timeout of {0} seconds but a timeout of {1} seconds was"
- " requested on the command line. Forcing timeout to be {1}"
- " seconds."
- ).format(lit_config.maxIndividualTestTime, opts.maxIndividualTestTime)
- )
- lit_config.maxIndividualTestTime = opts.maxIndividualTestTime
determine_order(discovered_tests, opts.order)
diff --git a/llvm/utils/lit/tests/Inputs/googletest-timeout/lit.cfg b/llvm/utils/lit/tests/Inputs/googletest-timeout/lit.cfg
index c1eab40f47e8d..200347aaf85c7 100644
--- a/llvm/utils/lit/tests/Inputs/googletest-timeout/lit.cfg
+++ b/llvm/utils/lit/tests/Inputs/googletest-timeout/lit.cfg
@@ -8,4 +8,4 @@ config.environment["GTEST_FILTER"] = lit_config.params.get("gtest_filter")
if configSetTimeout == "1":
# Try setting the max individual test time in the configuration
- lit_config.maxIndividualTestTime = 1
+ config.maxIndividualTestTime = 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-timeout/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-timeout/lit.cfg
index b78c0eac31d88..3a72f35024eb2 100644
--- a/llvm/utils/lit/tests/Inputs/shtest-timeout/lit.cfg
+++ b/llvm/utils/lit/tests/Inputs/shtest-timeout/lit.cfg
@@ -19,7 +19,7 @@ configSetTimeout = lit_config.params.get("set_timeout", "0")
if configSetTimeout != "0":
# Try setting the max individual test time in the configuration
- lit_config.maxIndividualTestTime = int(configSetTimeout)
+ config.maxIndividualTestTime = int(configSetTimeout)
config.test_format = lit.formats.ShTest(execute_external=externalShell)
config.suffixes = [".py"]
More information about the lldb-commits
mailing list