Summary
D154984 and D156954 propose changes to improve the usability of lit’s debug output, which is used by many lit users every day to understand lit test failures. Based on reviewer feedback so far, I have made multiple adjustments to those patches to avoid breaking use cases I was previously not aware of. The purpose of this RFC is to invite the broader LLVM community to check that we have not overlooked other important use cases.
Motivation
Currently, lit’s debug output for a test looks like the following:
Script:
--
: 'RUN: at line 1'; echo hello | FileCheck bogus.txt && echo success
--
Exit Code: 2
Command Output (stdout):
--
$ ":" "RUN: at line 1"
$ "echo" "hello"
# command output:
hello
$ "FileCheck" "bogus.txt"
# command stderr:
Could not open check file 'bogus.txt': No such file or directory
error: command failed with exit status: 2
--
(The “Caveat” section below discusses some cases when it doesn’t look like that.)
Notice that there are multiple sections:
- A
Script:
section shows all shell commands from the test’s RUN lines after lit substitution expansion. - A stdout section includes an execution trace that ends at the failed command.
- A stderr section would be printed next if it had content.
There are a number of issues with the current behavior:
- Redundant output: All shell commands that actually execute appear in the debug output twice, once in the
Script:
section, and once in the execution trace. Especially for tests with many RUN lines, the result seems unnecessarily noisy. When searching through the output for a particular shell command, it is easy to get lost and mistake shell commands underScript:
for shell commands that actually executed. - Unfaithful shell commands: In the execution trace, shell commands are not printed faithfully. They drop redirections. They break apart RUN lines at
&&
,|
, etc. Instead of using proper shell quoting, each command-line argument is blindly enclosed in double quotes. - Poorly delineated stdout/stderr: In the execution trace, shell command stdout, stderr, exit status, etc. are interleaved with the shell commands and are not clearly delineated.
- Difficult copy/paste of shell commands: While debugging a test, some lit users copy and paste shell commands into a terminal to reproduce results. For this purpose, copying shell commands from the execution trace seems convenient because the previous results of those commands are co-located with them. However, again, the commands are not always printed faithfully here. Moreover, because of the interleaved results, and because of the
$
at the start of every command, commands must be copied one at a time. Some lit users thus currently depend on theScript:
section for copying and pasting commands, but results are not co-located there for convenient comparison. - Execution trace disabled by default: Even when a test’s output is shown (requires
-v
for failed tests, or-a
for all tests), the execution trace is sometimes (see “Caveat” section below for when) disabled by default. In that case, to determine which command actually failed, the test usually needs to be run again with-vv
. - Future lit extensions: D154987 proposes PYTHON lines that can appear among RUN lines. How should they be represented in the
Script:
section, which has previously been just a shell script? Adding info about PYTHON lines in the execution trace seems more straight-forward and more useful, and D154987 already implements that. (I hope we can avoid debating PYTHON lines in this particular RFC, but I think it’s worthwhile to disclose the RFC’s full context.)
Changes
D154984 and D156954 convert the above output into the following:
Exit Code: 2
Command Output (stdout):
--
# RUN: at line 1
echo hello | FileCheck bogus-file.txt && echo success
# executed command: echo hello
# .---command stdout------------
# | hello
# `-----------------------------
# executed command: FileCheck bogus-file.txt
# .---command stderr------------
# | Could not open check file 'bogus-file.txt': No such file or directory
# `-----------------------------
# error: command failed with exit status: 2
--
They address the above issues as follows:
- The
Script:
section has been dropped entirely. - The entire execution trace can be copied and pasted in bulk to a terminal for correct execution of the RUN lines, which are printed intact as they appeared in the original RUN lines except lit substitutions are expanded. Everything else in the execution trace appears in shell comments so it has no effect in a terminal.
- Each of the RUN line’s commands is repeated (in shell comments) as it executes to show (1) that the command actually executed (e.g.,
echo success
above didn’t) and (2) what stdout, stderr, non-zero exit status, and output files are associated with the command, if any. Shell quoting in the command is now correct and minimal. - The start and end of the contents of stdout, stderr, or an output file is now delineated clearly in the trace.
- If a test’s debug output is shown by
-v
or-a
, the execution trace is always enabled, and-vv
has no additional effect. Without these patches,-vv
implied-v
, so these patches make them aliases for backward compatibility.
Caveat
Lit can be configured to execute RUN lines using either lit’s internal shell or an external shell (e.g., bash, sh, window’s cmd
). Lit’s internal shell is usually best for test portability because it’s implemented in python. To configure a test suite to use lit’s internal shell, make sure the following line appears in the test suite’s lit.cfg
or other configuration file:
config.test_format = lit.formats.ShTest(execute_external=False)
It is important to qualify the changes these patches make based on the shell that lit is configured to use:
- The changes these patches make for
-vv
affect external shells only. Lit’s internal shell already has the desired behavior that-v
and-a
always produce the execution trace and that-vv
is an alias for-v
. - All debug output examples shown above are for lit’s internal shell. The changes these patches make for the execution trace format affect lit’s internal shell only. In most cases, we do not know how to force external shells to produce execution traces in the manner we want, and the output looks quite different than shown in the examples above.
- These patches drop the
Script:
section for all shells.