Skip to content

Commit

Permalink
[lit] Drop "Script:", make -v and -a imply -vv
Browse files Browse the repository at this point in the history
This patch and D156954 were discussed in
<https://discourse.llvm.org/t/rfc-improving-lits-debug-output/72839>.

**Motivation**: -a shows output from all tests, and -v shows output
from just failed tests.  Without this patch, that output from each
test includes a section called "Script:", which includes all shell
commands that lit has computed from RUN directives and will attempt to
run for that test.  The effect of -vv (which also implies -v if
neither -a or -v is specified) is to extend that output with shell
commands as they are executing so you can easily see which one failed.

For example, when using lit's internal shell and -vv:

```
Script:
--
: 'RUN: at line 1'; echo hello world
: 'RUN: at line 2'; 3c40 hello world
: 'RUN: at line 3'; echo hello world
--
Exit Code: 127

Command Output (stdout):
--
$ ":" "RUN: at line 1"
$ "echo" "hello" "world"
hello world

$ ":" "RUN: at line 2"
$ "3c40" "hello" "world"
'3c40': command not found
error: command failed with exit status: 127

--
```

Notice that all shell commands that actually execute appear in the
output twice, once for "Script:" and once for -vv.  Especially for
tests with many RUN directives, the result is noisy.  When searching
through the output for a particular shell command, it is easy to get
lost and mistake shell commands under "Script:" for shell commands
that actually executed.

**Change**: With this patch, a test's output changes in two ways.
First, the "Script:" section is never shown.  Second, omitting -vv no
longer disables printing of shell commands as they execute.  That is,
-a and -v imply -vv, and so -vv is deprecated as it is just an alias
for -v.

**Secondary motivation**: We are also working to introduce a PYTHON
directive, which can appear between RUN directives.  How should PYTHON
directives be represented in the "Script:" section, which has
previously been just a shell script?  We could probably think of
something, but adding info about PYTHON directive execution in the -vv
trace seems more straight-forward and more useful.

(This patch also removes a confusing point in the -vv documentation:
at least when using bash as an external shell, -vv echoes commands to
the shell's stderr not stdout.)

Reviewed By: awarzynski, Endill, ldionne, MaskRay

Differential Revision: https://reviews.llvm.org/D154984
  • Loading branch information
jdenny-ornl committed Aug 29, 2023
1 parent 77e965e commit 09b6e45
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 139 deletions.
19 changes: 9 additions & 10 deletions llvm/docs/CommandGuide/lit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,20 @@ OUTPUT OPTIONS
Show more information on test failures, for example the entire test output
instead of just the test result.

Each command is printed before it is executed. This can be valuable for
debugging test failures, as the last printed command is the one that failed.
Moreover, :program:`lit` inserts a no-op command (``:`` in the case of bash)
with argument ``'RUN: at line N'`` before each command pipeline, and those
no-op commands are also printed to help you locate the source line of the
failed command.

.. option:: -vv, --echo-all-commands

On test failure, echo all commands to stdout as they are being executed.
This can be valuable for debugging test failures, as the last echoed command
will be the one which has failed.
:program:`lit` normally inserts a no-op command (``:`` in the case of bash)
with argument ``'RUN: at line N'`` before each command pipeline, and this
option also causes those no-op commands to be echoed to stdout to help you
locate the source line of the failed command.
This option implies ``--verbose``.
Deprecated alias for -v.

.. option:: -a, --show-all

Show more information about all tests, for example the entire test
commandline and output.
Enable -v, but for all tests not just failed tests.

.. option:: --no-progress-bar

Expand Down
2 changes: 0 additions & 2 deletions llvm/utils/lit/lit/LitConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def __init__(
config_prefix=None,
maxIndividualTestTime=0,
parallelism_groups={},
echo_all_commands=False,
per_test_coverage=False,
):
# The name of the test runner.
Expand Down Expand Up @@ -87,7 +86,6 @@ def __init__(

self.maxIndividualTestTime = maxIndividualTestTime
self.parallelism_groups = parallelism_groups
self.echo_all_commands = echo_all_commands
self.per_test_coverage = per_test_coverage

@property
Expand Down
10 changes: 3 additions & 7 deletions llvm/utils/lit/lit/TestRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -1102,10 +1102,7 @@ def executeScript(test, litConfig, tmpBase, commands, cwd):
commands[i] = match.expand(
"echo '\\1' > nul && " if command else "echo '\\1' > nul"
)
if litConfig.echo_all_commands:
f.write("@echo on\n")
else:
f.write("@echo off\n")
f.write("@echo on\n")
f.write("\n@if %ERRORLEVEL% NEQ 0 EXIT\n".join(commands))
else:
for i, ln in enumerate(commands):
Expand All @@ -1115,8 +1112,7 @@ def executeScript(test, litConfig, tmpBase, commands, cwd):
commands[i] = match.expand(": '\\1'; \\2" if command else ": '\\1'")
if test.config.pipefail:
f.write(b"set -o pipefail;" if mode == "wb" else "set -o pipefail;")
if litConfig.echo_all_commands:
f.write(b"set -x;" if mode == "wb" else "set -x;")
f.write(b"set -x;" if mode == "wb" else "set -x;")
if sys.version_info > (3, 0) and mode == "wb":
f.write(bytes("{ " + "; } &&\n{ ".join(commands) + "; }", "utf-8"))
else:
Expand Down Expand Up @@ -2086,7 +2082,7 @@ def runOnce(execdir):
status = Test.FLAKYPASS

# Form the output log.
output = """Script:\n--\n%s\n--\nExit Code: %d\n""" % ("\n".join(script), exitCode)
output = f"Exit Code: {exitCode}\n"

if timeoutInfo is not None:
output += """Timeout: %s\n""" % (timeoutInfo,)
Expand Down
14 changes: 6 additions & 8 deletions llvm/utils/lit/lit/cl_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,23 @@ def parse_args():
"-v",
"--verbose",
dest="showOutput",
help="Show test output for failures",
help="For failed tests, show all output. For example, each command is"
" printed before it is executed, so the last printed command is the one"
" that failed.",
action="store_true",
)
format_group.add_argument(
"-vv",
"--echo-all-commands",
dest="echoAllCommands",
dest="showOutput",
help="Deprecated alias for -v.",
action="store_true",
help="Echo all commands as they are executed to stdout. In case of "
"failure, last command shown will be the failing one.",
)
format_group.add_argument(
"-a",
"--show-all",
dest="showAllOutput",
help="Display all commandlines and output",
help="Enable -v, but for all tests not just failed tests.",
action="store_true",
)
format_group.add_argument(
Expand Down Expand Up @@ -299,9 +300,6 @@ def parse_args():
opts = parser.parse_args(args)

# Validate command line options
if opts.echoAllCommands:
opts.showOutput = True

if opts.incremental:
print(
"WARNING: --incremental is deprecated. Failing tests now always run first."
Expand Down
1 change: 0 additions & 1 deletion llvm/utils/lit/lit/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def main(builtin_params={}):
order=opts.order,
params=params,
config_prefix=opts.configPrefix,
echo_all_commands=opts.echoAllCommands,
per_test_coverage=opts.per_test_coverage,
)

Expand Down
112 changes: 84 additions & 28 deletions llvm/utils/lit/tests/Inputs/shtest-if-else/test.txt
Original file line number Diff line number Diff line change
@@ -1,92 +1,148 @@
# CHECK: -- Testing:{{.*}}
# CHECK-NEXT: PASS: shtest-if-else :: test.txt (1 of 1)
# CHECK-NEXT: Script:
# CHECK-NEXT: --
# CHECK: -- Testing:{{.*}}
# CHECK-NEXT: PASS: shtest-if-else :: test.txt (1 of 1)
# CHECK-NEXT: Exit Code: 0
# CHECK-EMPTY:
# CHECK-NEXT: Command Output (stdout):
# CHECK-NEXT: --

# RUN: %if feature %{ echo "test-1" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo "test-1"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: test-1
# CHECK-EMPTY:

# If %else is not present it is treated like %else %{%}. Empty commands
# are ignored.
#
# RUN: %if nofeature %{ echo "fail" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'
# CHECK-NOT: fail
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK-NOT: fail

# RUN: %if nofeature %{ echo "fail" %} %else %{ echo "test-2" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo "test-2"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: test-2
# CHECK-EMPTY:

# Spaces inside curly braces are not ignored
#
# RUN: echo test-%if feature %{ 3 %} %else %{ fail %}-test
# RUN: echo test-%if feature %{ 4 4 %} %else %{ fail %}-test
# RUN: echo test-%if nofeature %{ fail %} %else %{ 5 5 %}-test
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo test- 3 -test
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo test- 4 4 -test
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo test- 5 5 -test
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-3]]"
# CHECK: # command output:
# CHECK-NEXT: test- 3 -test
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-6]]"
# CHECK: # command output:
# CHECK-NEXT: test- 4 4 -test
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-9]]"
# CHECK: # command output:
# CHECK-NEXT: test- 5 5 -test
# CHECK-EMPTY:

# Escape line breaks for multi-line expressions
#
# RUN: %if feature \
# RUN: %{ echo \
# RUN: "test-5" \
# RUN: %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-4]]'; echo "test-5"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-4]]"
# CHECK: # command output:
# CHECK-NEXT: test-5
# CHECK-EMPTY:

# RUN: %if nofeature \
# RUN: %{ echo "fail" %} \
# RUN: %else \
# RUN: %{ echo "test-6" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-4]]'; echo "test-6"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-4]]"
# CHECK: # command output:
# CHECK-NEXT: test-6
# CHECK-EMPTY:

# RUN: echo "test%if feature %{%} %else %{%}-7"
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo "test-7"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: test-7
# CHECK-EMPTY:

# Escape %if. Without %if..%else context '%{' and '%}' are treated
# literally.
#
# RUN: echo %%if feature %{ echo "test-8" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo %if feature %{ echo "test-8" %}
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: %if feature %{ echo test-8 %}
# CHECK-EMPTY:

# Nested expressions are supported:
#
# RUN: echo %if feature %{ %if feature %{ %if nofeature %{"fail"%} %else %{"test-9"%} %} %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo "test-9"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: test-9
# CHECK-EMPTY:

# Binary expression evaluation and regex match can be used as
# conditions.
#
# RUN: echo %if feature && !nofeature %{ "test-10" %}
# RUN: echo %if feature && nofeature %{ "fail" %} %else %{ "test-11" %}
# RUN: echo %if {{fea.+}} %{ "test-12" %} %else %{ "fail" %}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo "test-10"
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo "test-11"
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo "test-12"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-3]]"
# CHECK: # command output:
# CHECK-NEXT: test-10
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-6]]"
# CHECK: # command output:
# CHECK-NEXT: test-11
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-9]]"
# CHECK: # command output:
# CHECK-NEXT: test-12
# CHECK-EMPTY:

# Spaces between %if and %else are ignored. If there is no %else -
# space after %if %{...%} is not ignored.
#
# RUN: echo XX %if feature %{YY%} ZZ
# RUN: echo AA %if feature %{BB%} %else %{CC%} DD
# RUN: echo AA %if nofeature %{BB%} %else %{CC%} DD
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo XX YY ZZ
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo AA BB DD
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-3]]'; echo AA CC DD
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-3]]"
# CHECK: # command output:
# CHECK-NEXT: XX YY ZZ
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-6]]"
# CHECK: # command output:
# CHECK-NEXT: AA BB DD
# CHECK-EMPTY:
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-9]]"
# CHECK: # command output:
# CHECK-NEXT: AA CC DD
# CHECK-EMPTY:

# '{' and '}' can be used without escaping
#
# RUN: %if feature %{echo {}%}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo {}
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: {}
# CHECK-EMPTY:

# Spaces are not required
#
# RUN: echo %if feature%{"ok"%}%else%{"fail"%}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo "ok"
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: ok
# CHECK-EMPTY:

# Substitutions with braces are handled correctly
#
# RUN: echo %{sub} %if feature%{test-%{sub}%}%else%{"fail"%}
# CHECK-NEXT: {{^.*'RUN}}: at line [[#@LINE-1]]'; echo ok test-ok

# CHECK-NEXT: --
# CHECK-NEXT: Exit Code: 0
# CHECK-NEXT: {{^.*"RUN}}: at line [[#@LINE-1]]"
# CHECK: # command output:
# CHECK-NEXT: ok test-ok
# CHECK-EMPTY:
61 changes: 32 additions & 29 deletions llvm/utils/lit/tests/shtest-format.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,19 @@

# CHECK: PASS: shtest-format :: external_shell/pass.txt

# CHECK: FAIL: shtest-format :: fail.txt
# CHECK-NEXT: *** TEST 'shtest-format :: fail.txt' FAILED ***
# CHECK-NEXT: Script:
# CHECK-NEXT: --
# CHECK-NEXT: printf "line 1
# CHECK-NEXT: false
# CHECK-NEXT: --
# CHECK-NEXT: Exit Code: 1
#
# CHECK: Command Output (stdout):
# CHECK-NEXT: --
# CHECK-NEXT: $ ":" "RUN: at line 1"
# CHECK-NEXT: $ "printf"
# CHECK-NEXT: # command output:
# CHECK-NEXT: line 1: failed test output on stdout
# CHECK-NEXT: line 2: failed test output on stdout
# CHECK: FAIL: shtest-format :: fail.txt
# CHECK-NEXT: *** TEST 'shtest-format :: fail.txt' FAILED ***
# CHECK-NEXT: Exit Code: 1
# CHECK-EMPTY:
# CHECK-NEXT: Command Output (stdout):
# CHECK-NEXT: --
# CHECK-NEXT: $ ":" "RUN: at line 1"
# CHECK-NEXT: $ "printf"
# CHECK-NEXT: # command output:
# CHECK-NEXT: line 1: failed test output on stdout
# CHECK-NEXT: line 2: failed test output on stdout
# CHECK-NEXT: $ ":" "RUN: at line 2"
# CHECK-NEXT: $ "false"

# CHECK: UNRESOLVED: shtest-format :: no-test-line.txt
# CHECK: PASS: shtest-format :: pass.txt
Expand All @@ -69,12 +66,15 @@
# CHECK: XFAIL: shtest-format :: xfail-feature.txt
# CHECK: XFAIL: shtest-format :: xfail-target.txt
# CHECK: XFAIL: shtest-format :: xfail.txt
# CHECK: XPASS: shtest-format :: xpass.txt
# CHECK-NEXT: *** TEST 'shtest-format :: xpass.txt' FAILED ***
# CHECK-NEXT: Script
# CHECK-NEXT: --
# CHECK-NEXT: true
# CHECK-NEXT: --

# CHECK: XPASS: shtest-format :: xpass.txt
# CHECK-NEXT: *** TEST 'shtest-format :: xpass.txt' FAILED ***
# CHECK-NEXT: Exit Code: 0
# CHECK-EMPTY:
# CHECK-NEXT: Command Output (stdout):
# CHECK-NEXT: --
# CHECK-NEXT: $ ":" "RUN: at line 1"
# CHECK-NEXT: $ "true"

# CHECK: Failed Tests (4)
# CHECK: shtest-format :: external_shell/fail.txt
Expand Down Expand Up @@ -109,13 +109,16 @@
# XUNIT: </failure>
# XUNIT-NEXT: </testcase>

# XUNIT: <testcase classname="shtest-format.external_shell" name="fail_with_control_chars.txt" time="{{[0-9]+\.[0-9]+}}">
# XUNIT-NEXT: <failure><![CDATA[Script:
# XUNIT: Command Output (stdout):
# XUNIT-NEXT: --
# XUNIT-NEXT: a line with [2;30;41mcontrol characters[0m.
# XUNIT: </failure>
# XUNIT-NEXT: </testcase>
# XUNIT: <testcase classname="shtest-format.external_shell" name="fail_with_control_chars.txt" time="{{[0-9]+\.[0-9]+}}">
# XUNIT-NEXT: <failure><![CDATA[Exit Code: 1
# XUNIT-EMPTY:
# XUNIT-NEXT: Command Output (stdout):
# XUNIT-NEXT: --
# XUNIT-NEXT: a line with [2;30;41mcontrol characters[0m.
# XUNIT-EMPTY:
# XUNIT-NEXT: --
# XUNIT: ]]></failure>
# XUNIT-NEXT: </testcase>

# XUNIT: <testcase classname="shtest-format.external_shell" name="pass.txt" time="{{[0-9]+\.[0-9]+}}"/>

Expand Down

0 comments on commit 09b6e45

Please sign in to comment.