[libc-commits] [libc] [libc] Fix integration test args/env in LibcTest lit format (PR #184438)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Tue Mar 3 13:08:44 PST 2026


https://github.com/kaladron created https://github.com/llvm/llvm-project/pull/184438

Integration tests with ARGS or ENV in their add_integration_test() call were being run with no arguments or environment variables by the LibcTest lit format, causing failures in startup_args_test, sprintf_size_test, getenv_test, execv_test, execve_test, and getcwd_test.

Fix this by having add_integration_test() emit a sidecar <executable>.params JSON file (via file(GENERATE)) whenever ARGS or ENV are specified. LibcTest.execute() reads this file at test time and passes the args and environment to the test executable.

Also always set PWD=exec_dir in the test environment so that getenv("PWD") matches getcwd() for tests that compare them.

>From 64f16fcd71dfea761a778f4f5c86c6ec64a45a4e Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Tue, 3 Mar 2026 21:06:28 +0000
Subject: [PATCH] [libc] Fix integration test args/env in LibcTest lit format

Integration tests with ARGS or ENV in their add_integration_test() call
were being run with no arguments or environment variables by the LibcTest
lit format, causing failures in startup_args_test, sprintf_size_test,
getenv_test, execv_test, execve_test, and getcwd_test.

Fix this by having add_integration_test() emit a sidecar
<executable>.params JSON file (via file(GENERATE)) whenever ARGS or ENV
are specified. LibcTest.execute() reads this file at test time and passes
the args and environment to the test executable.

Also always set PWD=exec_dir in the test environment so that
getenv("PWD") matches getcwd() for tests that compare them.
---
 libc/cmake/modules/LLVMLibCTestRules.cmake | 19 +++++++++++
 libc/utils/libctest/format.py              | 39 ++++++++++++++++++++--
 2 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index ba75f2130620b..6759bb9fb833e 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -641,6 +641,25 @@ function(add_integration_test test_name)
       ${CMAKE_CROSSCOMPILING_EMULATOR}
       ${INTEGRATION_TEST_LOADER_ARGS}
       $<TARGET_FILE:${fq_build_target_name}> ${INTEGRATION_TEST_ARGS})
+  # Generate a sidecar .params file alongside the executable for any test that
+  # requires specific command-line arguments or environment variables.  The
+  # LibcTest lit format reads this file at test time.  Format: one arg per line,
+  # a "---" separator, then one KEY=VALUE env entry per line.
+  if(INTEGRATION_TEST_ARGS OR INTEGRATION_TEST_ENV)
+    set(_params_content "")
+    foreach(_arg IN LISTS INTEGRATION_TEST_ARGS)
+      string(APPEND _params_content "${_arg}\n")
+    endforeach()
+    string(APPEND _params_content "---\n")
+    foreach(_env_entry IN LISTS INTEGRATION_TEST_ENV)
+      string(APPEND _params_content "${_env_entry}\n")
+    endforeach()
+    file(GENERATE
+      OUTPUT  "${CMAKE_CURRENT_BINARY_DIR}/${fq_build_target_name}.params"
+      CONTENT "${_params_content}"
+    )
+  endif()
+
   add_custom_target(
     ${fq_target_name}
     COMMAND ${test_cmd}
diff --git a/libc/utils/libctest/format.py b/libc/utils/libctest/format.py
index 82f65586e8b3b..6df14d069b652 100644
--- a/libc/utils/libctest/format.py
+++ b/libc/utils/libctest/format.py
@@ -16,6 +16,10 @@
 directory), following the pattern used by llvm/test/Unit/lit.cfg.py.
 
 Test executables are discovered by _isTestExecutable() and run by execute().
+
+Integration tests that require command-line arguments or environment variables
+have a sidecar <executable>.params file generated by CMake.  The format is
+one arg per line, a "---" separator, then one KEY=VALUE env entry per line.
 """
 
 import os
@@ -91,20 +95,51 @@ def execute(self, test, litConfig):
 
         Runs from the executable's directory so relative paths (like
         testdata/test.txt) work correctly.
+
+        If a sidecar <executable>.params file exists, it supplies the
+        command-line arguments and environment variables for the test.
         """
 
         test_path = test.getSourcePath()
         exec_dir = os.path.dirname(test_path)
 
+        # Read optional sidecar .params file generated by CMake for tests that
+        # need specific args/env (e.g. integration tests with ARGS/ENV).
+        # 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):
+            with open(params_path) as f:
+                content = f.read()
+            args_section, _, env_section = content.partition("---\n")
+            extra_args = [l for l in args_section.splitlines() if l]
+            for line in env_section.splitlines():
+                if "=" in line:
+                    k, _, v = line.partition("=")
+                    extra_env[k] = v
+
+        # Build the environment: inherit the current process environment, then
+        # set PWD to exec_dir so getenv("PWD") matches getcwd(), then overlay
+        # any test-specific variables from the .params file.
+        env = dict(os.environ)
+        env["PWD"] = exec_dir
+        env.update(extra_env)
+
         test_cmd_template = getattr(test.config, "libc_test_cmd", "")
         if test_cmd_template:
             test_cmd = test_cmd_template.replace("@BINARY@", test_path)
             cmd_args = shlex.split(test_cmd)
             if not cmd_args:
                 cmd_args = [test_path]
-            out, err, exit_code = lit.util.executeCommand(cmd_args, cwd=exec_dir)
+            cmd_args = cmd_args + extra_args
+            out, err, exit_code = lit.util.executeCommand(
+                cmd_args, cwd=exec_dir, env=env
+            )
         else:
-            out, err, exit_code = lit.util.executeCommand([test_path], cwd=exec_dir)
+            out, err, exit_code = lit.util.executeCommand(
+                [test_path] + extra_args, cwd=exec_dir, env=env
+            )
 
         if not exit_code:
             return lit.Test.PASS, ""



More information about the libc-commits mailing list