From 079be4e73982e1c7e0cddb8f9bd1b2009c6fb720 Mon Sep 17 00:00:00 2001 From: Jeff Bailey Date: Mon, 23 Mar 2026 16:39:40 +0000 Subject: [PATCH] [libc] Support Windows test executables in LibcTest lit format (#188057) Updated LibcTest to handle Windows test executables: * Added support for .exe extensions when identifying test executables. * Skipped the executable bit check on Windows as it is not applicable. * Updated .params file discovery to look for both .exe.params and .params. This allows running libc tests on Windows hosts. --- libc/utils/libctest/format.py | 40 +++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/libc/utils/libctest/format.py b/libc/utils/libctest/format.py index 6df14d069b65..c8280fd1b556 100644 --- a/libc/utils/libctest/format.py +++ b/libc/utils/libctest/format.py @@ -24,12 +24,16 @@ one arg per line, a "---" separator, then one KEY=VALUE env entry per line. import os import shlex +import sys import lit.formats import lit.Test import lit.util +kIsWindows = sys.platform in ["win32", "cygwin"] + + class LibcTest(lit.formats.ExecutableTest): """ Test format for libc unit tests. @@ -64,7 +68,8 @@ class LibcTest(lit.formats.ExecutableTest): """ Check if a file is a libc test executable we should run. - Recognized patterns (all must end with .__build__): + Recognized patterns (all must end with .__build__, optionally followed + by .exe on Windows): libc.test.src...__build__ libc.test.src...__unit__[....].__build__ libc.test.src...__hermetic__[....].__build__ @@ -72,23 +77,40 @@ class LibcTest(lit.formats.ExecutableTest): libc.test.include..__hermetic__[....].__build__ libc.test.integration...__build__ """ - if not filename.endswith(".__build__"): + test_name = filename + if kIsWindows and filename.endswith(".exe"): + test_name = filename[: -len(".exe")] + + if not test_name.endswith(".__build__"): return False - if filename.startswith("libc.test.src."): + if test_name.startswith("libc.test.src."): pass # Accept all src tests ending in .__build__ - elif filename.startswith("libc.test.include."): - if ".__unit__." not in filename and ".__hermetic__." not in filename: + elif test_name.startswith("libc.test.include."): + if ".__unit__." not in test_name and ".__hermetic__." not in test_name: return False - elif filename.startswith("libc.test.integration."): + elif test_name.startswith("libc.test.integration."): pass # Accept all integration tests ending in .__build__ else: return False if not os.path.isfile(filepath): return False - if not os.access(filepath, os.X_OK): + if not kIsWindows and not os.access(filepath, os.X_OK): return False return True + def _getParamsPath(self, test_path): + params_path = test_path + ".params" + if os.path.isfile(params_path): + return params_path + + root, ext = os.path.splitext(test_path) + if ext.lower() == ".exe": + params_path = root + ".params" + if os.path.isfile(params_path): + return params_path + + return None + def execute(self, test, litConfig): """ Execute a test by running the test executable. @@ -108,8 +130,8 @@ class LibcTest(lit.formats.ExecutableTest): # Format: one arg per line, "---" separator, then KEY=VALUE env lines. extra_args = [] extra_env = {} - params_path = test_path + ".params" - if os.path.isfile(params_path): + params_path = self._getParamsPath(test_path) + if params_path: with open(params_path) as f: content = f.read() args_section, _, env_section = content.partition("---\n")