[llvm] 75dba8e - [lit] Add readfile substitution
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 19 08:24:08 PDT 2025
Author: Aiden Grossman
Date: 2025-09-19T08:24:05-07:00
New Revision: 75dba8ea9ee164a297066afae437bc379f86f482
URL: https://github.com/llvm/llvm-project/commit/75dba8ea9ee164a297066afae437bc379f86f482
DIFF: https://github.com/llvm/llvm-project/commit/75dba8ea9ee164a297066afae437bc379f86f482.diff
LOG: [lit] Add readfile substitution
This patch adds a new %{readfile:<file name>} substitution to lit. This
is needed for porting a couple of tests to lit's internal shell. These
tests are all using subshells to pass some option to a command are not
feasible to run within the internal shell without this functionality.
Reviewers: petrhosek, jh7370, ilovepi, cmtice
Reviewed By: jh7370, cmtice
Pull Request: https://github.com/llvm/llvm-project/pull/158441
Added:
llvm/utils/lit/tests/Inputs/shtest-readfile/absolute-paths.txt
llvm/utils/lit/tests/Inputs/shtest-readfile/file-does-not-exist.txt
llvm/utils/lit/tests/Inputs/shtest-readfile/lit.cfg
llvm/utils/lit/tests/Inputs/shtest-readfile/relative-paths.txt
llvm/utils/lit/tests/Inputs/shtest-readfile/two-same-line.txt
llvm/utils/lit/tests/shtest-readfile.py
Modified:
llvm/docs/CommandGuide/lit.rst
llvm/utils/lit/lit/TestRunner.py
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/lit.rst b/llvm/docs/CommandGuide/lit.rst
index 15c249d8e6d31..359e0c3e81d0e 100644
--- a/llvm/docs/CommandGuide/lit.rst
+++ b/llvm/docs/CommandGuide/lit.rst
@@ -664,6 +664,7 @@ TestRunner.py:
Otherwise, %t but with a single leading ``/`` removed.
%:T On Windows, %/T but a ``:`` is removed if its the second character.
Otherwise, %T but with a single leading ``/`` removed.
+ %{readfile:<filename>} Reads the file specified.
======================= ==============
Other substitutions are provided that are variations on this base set and
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 90c2c6479b004..b4d7c98692337 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -720,6 +720,30 @@ def processRedirects(cmd, stdin_source, cmd_shenv, opened_files):
return std_fds
+def _expandLateSubstitutions(cmd, arguments, cwd):
+ for i, arg in enumerate(arguments):
+ if not isinstance(arg, str):
+ continue
+
+ def _replaceReadFile(match):
+ filePath = match.group(1)
+ if not os.path.isabs(filePath):
+ filePath = os.path.join(cwd, filePath)
+ try:
+ with open(filePath) as fileHandle:
+ return fileHandle.read()
+ except FileNotFoundError:
+ raise InternalShellError(
+ cmd,
+ "File specified in readfile substitution does not exist: %s"
+ % filePath,
+ )
+
+ arguments[i] = re.sub(r"%{readfile:([^}]*)}", _replaceReadFile, arg)
+
+ return arguments
+
+
def _executeShCmd(cmd, shenv, results, timeoutHelper):
if timeoutHelper.timeoutReached():
# Prevent further recursion if the timeout has been hit
@@ -834,6 +858,9 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
# Ensure args[0] is hashable.
args[0] = expand_glob(args[0], cmd_shenv.cwd)[0]
+ # Expand all late substitutions.
+ args = _expandLateSubstitutions(j, args, cmd_shenv.cwd)
+
inproc_builtin = inproc_builtins.get(args[0], None)
if inproc_builtin and (args[0] != "echo" or len(cmd.commands) == 1):
# env calling an in-process builtin is useless, so we take the safe
diff --git a/llvm/utils/lit/tests/Inputs/shtest-readfile/absolute-paths.txt b/llvm/utils/lit/tests/Inputs/shtest-readfile/absolute-paths.txt
new file mode 100644
index 0000000000000..d11feeba68672
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-readfile/absolute-paths.txt
@@ -0,0 +1,6 @@
+## Tests that readfile works with absolute paths.
+# RUN: echo -n "hello" > %t
+# RUN: echo %{readfile:%t}
+
+## Fail the test so we can assert on the output.
+# RUN: not echo return
diff --git a/llvm/utils/lit/tests/Inputs/shtest-readfile/file-does-not-exist.txt b/llvm/utils/lit/tests/Inputs/shtest-readfile/file-does-not-exist.txt
new file mode 100644
index 0000000000000..1151b75f2fa00
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-readfile/file-does-not-exist.txt
@@ -0,0 +1,4 @@
+## Test that readfile reports information appropriately when the file specified
+## does not exist.
+
+# RUN: echo %{readfile:/file/does/not/exist}
diff --git a/llvm/utils/lit/tests/Inputs/shtest-readfile/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-readfile/lit.cfg
new file mode 100644
index 0000000000000..cf453e1ea786f
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-readfile/lit.cfg
@@ -0,0 +1,7 @@
+import lit.formats
+
+config.name = "shtest-readfile"
+config.suffixes = [".txt"]
+config.test_format = lit.formats.ShTest(execute_external=False)
+config.test_source_root = None
+config.test_exec_root = None
diff --git a/llvm/utils/lit/tests/Inputs/shtest-readfile/relative-paths.txt b/llvm/utils/lit/tests/Inputs/shtest-readfile/relative-paths.txt
new file mode 100644
index 0000000000000..08a8170773a21
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-readfile/relative-paths.txt
@@ -0,0 +1,7 @@
+## Tests that readfile works with relative paths.
+# RUN: mkdir -p rel_path_test_folder
+# RUN: echo -n "hello" > rel_path_test_folder/test_file
+# RUN: echo %{readfile:rel_path_test_folder/test_file}
+
+## Fail the test so we can assert on the output.
+# RUN: not echo return
diff --git a/llvm/utils/lit/tests/Inputs/shtest-readfile/two-same-line.txt b/llvm/utils/lit/tests/Inputs/shtest-readfile/two-same-line.txt
new file mode 100644
index 0000000000000..7a8eb2c3e5332
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-readfile/two-same-line.txt
@@ -0,0 +1,8 @@
+## Tests that readfile works with two substitutions on the same line to ensure the
+## regular expressions are set up correctly.
+# RUN: echo -n "hello" > %t.1
+# RUN: echo -n "bye" > %t.2
+# RUN: echo %{readfile:%t.1} %{readfile:%t.2}
+
+## Fail the test so we can assert on the output.
+# RUN: not echo return
diff --git a/llvm/utils/lit/tests/shtest-readfile.py b/llvm/utils/lit/tests/shtest-readfile.py
new file mode 100644
index 0000000000000..91250b2afb3f2
--- /dev/null
+++ b/llvm/utils/lit/tests/shtest-readfile.py
@@ -0,0 +1,21 @@
+## Tests the readfile substitution.
+
+# RUN: not %{lit} -a -v %{inputs}/shtest-readfile | FileCheck -match-full-lines -DTEMP_PATH=%S%{fs-sep}Inputs%{fs-sep}shtest-readfile%{fs-sep}Output %s
+
+# CHECK: -- Testing: 4 tests{{.*}}
+
+# CHECK-LABEL: FAIL: shtest-readfile :: absolute-paths.txt ({{[^)]*}})
+# CHECK: echo hello
+# CHECK: # executed command: echo '%{readfile:[[TEMP_PATH]]{{[\\\/]}}absolute-paths.txt.tmp}'
+
+# CHECK-LABEL: FAIL: shtest-readfile :: file-does-not-exist.txt ({{[^)]*}})
+# CHECK: # executed command: @echo 'echo %{readfile:/file/does/not/exist}'
+# CHECK: # | File specified in readfile substitution does not exist: /file/does/not/exist
+
+# CHECK-LABEL: FAIL: shtest-readfile :: relative-paths.txt ({{[^)]*}})
+# CHECK: echo hello
+# CHECK: # executed command: echo '%{readfile:rel_path_test_folder/test_file}'
+
+# CHECK-LABEL: FAIL: shtest-readfile :: two-same-line.txt ({{[^)]*}})
+# CHECK: echo hello bye
+# CHECK: # executed command: echo '%{readfile:[[TEMP_PATH]]{{[\\\/]}}two-same-line.txt.tmp.1}' '%{readfile:[[TEMP_PATH]]{{[\\\/]}}two-same-line.txt.tmp.2}'
More information about the llvm-commits
mailing list