[Lldb-commits] [lldb] [llvm] [lit] Enforce read-only behavior on lit_config.maxIndividualTestTime (PR #198193)
Vitaly Buka via lldb-commits
lldb-commits at lists.llvm.org
Tue May 26 22:48:17 PDT 2026
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/198193
>From 6ae15a11245f43273582497e2446500c78ce1b90 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 17 May 2026 10:10:56 -0700
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.7
[skip ci]
---
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 | 20 +++++++++++++++++++
llvm/utils/lit/lit/formats/googletest.py | 4 ++--
llvm/utils/lit/lit/main.py | 13 +-----------
.../tests/Inputs/googletest-timeout/lit.cfg | 2 +-
.../lit/tests/Inputs/shtest-timeout/lit.cfg | 2 +-
.../lit/tests/Inputs/timeout-config/lit.cfg | 13 ++++++++++++
.../lit/tests/Inputs/timeout-config/test.py | 1 +
llvm/utils/lit/tests/timeout-config.py | 9 +++++++++
14 files changed, 60 insertions(+), 25 deletions(-)
create mode 100644 llvm/utils/lit/tests/Inputs/timeout-config/lit.cfg
create mode 100644 llvm/utils/lit/tests/Inputs/timeout-config/test.py
create mode 100644 llvm/utils/lit/tests/timeout-config.py
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 c92b104c9227c..d50bc4ce3e03f 100644
--- a/lldb/test/API/lit.cfg.py
+++ b/lldb/test/API/lit.cfg.py
@@ -192,7 +192,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 64107001e3aae..9e7f6cad9696d 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 4be2a0f6d8121..6c14c943d6dcc 100644
--- a/llvm/utils/lit/lit/LitConfig.py
+++ b/llvm/utils/lit/lit/LitConfig.py
@@ -36,7 +36,7 @@ def __init__(
order,
params,
config_prefix=None,
- maxIndividualTestTime=0,
+ maxIndividualTestTime=None,
maxRetriesPerTest=None,
parallelism_groups={},
per_test_coverage=False,
@@ -124,6 +124,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 82852f1852705..2c14aaeb8f2f4 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 4bed1c95decd4..3efe670c26269 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.
@@ -226,6 +229,7 @@ def recursiveExpansionLimit(self, value):
)
self._recursiveExpansionLimit = value
+
def finish(self, litConfig):
"""finish() - Finish this config object, after loading is complete."""
@@ -247,6 +251,22 @@ def finish(self, litConfig):
and getattr(self, "test_retry_attempts", None) is None
):
self.test_retry_attempts = litConfig.maxRetriesPerTest
+ 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 01820da38c954..75dee5859a27e 100644
--- a/llvm/utils/lit/lit/formats/googletest.py
+++ b/llvm/utils/lit/lit/formats/googletest.py
@@ -192,7 +192,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:
@@ -200,7 +200,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"]
diff --git a/llvm/utils/lit/tests/Inputs/timeout-config/lit.cfg b/llvm/utils/lit/tests/Inputs/timeout-config/lit.cfg
new file mode 100644
index 0000000000000..1611667409f61
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/timeout-config/lit.cfg
@@ -0,0 +1,13 @@
+# -*- Python -*-
+import os
+import sys
+import lit.formats
+
+config.name = "timeout-config"
+config.test_format = lit.formats.ShTest()
+config.suffixes = [".py"]
+config.test_source_root = os.path.dirname(__file__)
+config.test_exec_root = config.test_source_root
+config.maxIndividualTestTime = 1
+
+config.substitutions.append(("%{python}", '"%s"' % (sys.executable)))
diff --git a/llvm/utils/lit/tests/Inputs/timeout-config/test.py b/llvm/utils/lit/tests/Inputs/timeout-config/test.py
new file mode 100644
index 0000000000000..aaedc91a1ac38
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/timeout-config/test.py
@@ -0,0 +1 @@
+# RUN: %{python} -c "import time; time.sleep(10)"
diff --git a/llvm/utils/lit/tests/timeout-config.py b/llvm/utils/lit/tests/timeout-config.py
new file mode 100644
index 0000000000000..3305a606701d2
--- /dev/null
+++ b/llvm/utils/lit/tests/timeout-config.py
@@ -0,0 +1,9 @@
+# REQUIRES: lit-max-individual-test-time
+# UNSUPPORTED: system-windows
+
+# RUN: not %{lit} \
+# RUN: %{inputs}/timeout-config \
+# RUN: -j 1 -v > %t.out 2> %t.err
+# RUN: FileCheck < %t.out %s
+
+# CHECK: TIMEOUT: timeout-config :: test.py
>From 3597ec5cf4b1a8fb7d82327ce0331ddc72f3302f Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 17 May 2026 11:42:54 -0700
Subject: [PATCH 2/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.7
[skip ci]
---
llvm/utils/lit/lit/TestingConfig.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/lit/lit/TestingConfig.py b/llvm/utils/lit/lit/TestingConfig.py
index ade70bb31b1b8..3d42cfe304d6f 100644
--- a/llvm/utils/lit/lit/TestingConfig.py
+++ b/llvm/utils/lit/lit/TestingConfig.py
@@ -250,6 +250,7 @@ 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:
>From 5954e212a9138c5a18219ba3c1f486e89114467e Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Tue, 26 May 2026 22:48:06 -0700
Subject: [PATCH 3/3] feedback addressed
Created using spr 1.3.7
---
llvm/utils/lit/tests/Inputs/lit-config-readonly/dummy.txt | 1 -
llvm/utils/lit/tests/Inputs/lit-config-readonly/lit.cfg | 1 -
llvm/utils/lit/tests/lit-config-readonly.py | 2 +-
3 files changed, 1 insertion(+), 3 deletions(-)
delete mode 100644 llvm/utils/lit/tests/Inputs/lit-config-readonly/dummy.txt
diff --git a/llvm/utils/lit/tests/Inputs/lit-config-readonly/dummy.txt b/llvm/utils/lit/tests/Inputs/lit-config-readonly/dummy.txt
deleted file mode 100644
index 18f9fae2ad451..0000000000000
--- a/llvm/utils/lit/tests/Inputs/lit-config-readonly/dummy.txt
+++ /dev/null
@@ -1 +0,0 @@
-# dummy test
diff --git a/llvm/utils/lit/tests/Inputs/lit-config-readonly/lit.cfg b/llvm/utils/lit/tests/Inputs/lit-config-readonly/lit.cfg
index 14940dfc0ec34..39d3396b29d34 100644
--- a/llvm/utils/lit/tests/Inputs/lit-config-readonly/lit.cfg
+++ b/llvm/utils/lit/tests/Inputs/lit-config-readonly/lit.cfg
@@ -1,4 +1,3 @@
-# -*- Python -*-
import os
import lit.formats
diff --git a/llvm/utils/lit/tests/lit-config-readonly.py b/llvm/utils/lit/tests/lit-config-readonly.py
index 3ecf693b5730c..e15e79b9668bc 100644
--- a/llvm/utils/lit/tests/lit-config-readonly.py
+++ b/llvm/utils/lit/tests/lit-config-readonly.py
@@ -1,4 +1,4 @@
-# RUN: not %{lit} %{inputs}/lit-config-readonly > %t.out 2> %t.err
+# RUN: not %{lit} %{inputs}/lit-config-readonly 2> %t.err
# RUN: FileCheck --check-prefix=CHECK-ERR < %t.err %s
# CHECK-ERR: AttributeError: lit_config.maxIndividualTestTime is read-only. Use config.maxIndividualTestTime instead.
More information about the lldb-commits
mailing list