[llvm] f1b4c4b - [lit] Fix `not` calling internal commands

Joel E. Denny via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 5 11:09:43 PST 2019


Author: Joel E. Denny
Date: 2019-11-05T14:09:21-05:00
New Revision: f1b4c4bfd0b55c3c0abbc73e1159117f8533aca3

URL: https://github.com/llvm/llvm-project/commit/f1b4c4bfd0b55c3c0abbc73e1159117f8533aca3
DIFF: https://github.com/llvm/llvm-project/commit/f1b4c4bfd0b55c3c0abbc73e1159117f8533aca3.diff

LOG: [lit] Fix `not` calling internal commands

Without this patch, when using lit's internal shell, if `not` on a lit
RUN line calls `env`, `diff`, or any of the other in-process shell
builtins that lit implements, lit accidentally searches for the latter
as an external executable.  What's worse is that works fine when a
developer is testing on a platform where those executables are
available and behave as expected, but it then breaks on other
platforms.

`not` seems useful for some builtins, such as `diff`, so this patch
supports such uses.  `not --crash` does not seem useful for builtins,
so this patch diagnoses such uses.  In all cases, this patch ensures
shell builtins are found behind any sequence of `env` and `not`
commands.

`not` calling `env` calling an external command appears useful when
the `env` and external command are part of a lit substitution, as in
D65156.  This patch supports that by looking through any sequence of
`env` and `not` commands, building the environment from the `env`s,
and storing the `not`s.  The `not`s are then added back to the command
line without the `env`s to execute externally.  This avoids the need
to replicate the `not` implementation, in particular the `--crash`
option, in lit.

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D66531

Added: 
    llvm/utils/lit/tests/Inputs/shtest-env/env-calls-not-builtin.txt
    llvm/utils/lit/tests/Inputs/shtest-not/fail.py
    llvm/utils/lit/tests/Inputs/shtest-not/lit.cfg
    llvm/utils/lit/tests/Inputs/shtest-not/not-args-last-is-crash.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-args-nested-none.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-args-none.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-cd.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-colon.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-diff-with-crash.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-diff.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-echo.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-env-builtin.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-export.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-external.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-mkdir.txt
    llvm/utils/lit/tests/Inputs/shtest-not/not-calls-rm.txt
    llvm/utils/lit/tests/Inputs/shtest-not/pass.py
    llvm/utils/lit/tests/Inputs/shtest-not/print_environment.py
    llvm/utils/lit/tests/shtest-not.py

Modified: 
    llvm/utils/lit/lit/TestRunner.py
    llvm/utils/lit/tests/shtest-env.py

Removed: 
    


################################################################################
diff  --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 0f385a5376f2..9f310a82d3b2 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -17,7 +17,7 @@
 except ImportError:
     from io import StringIO
 
-from lit.ShCommands import GlobItem
+from lit.ShCommands import GlobItem, Command
 import lit.ShUtil as ShUtil
 import lit.Test as Test
 import lit.util
@@ -627,19 +627,34 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
         # Reference the global environment by default.
         cmd_shenv = shenv
         args = list(j.args)
-        while args[0] == 'env':
-            # Create a copy of the global environment and modify it for this one
-            # command. There might be multiple envs in a pipeline, and
-            # there might be multiple envs in a command (usually when one comes
-            # from a substitution):
-            #   env FOO=1 llc < %s | env BAR=2 llvm-mc | FileCheck %s
-            #   env FOO=1 %{another_env_plus_cmd} | FileCheck %s
-            if cmd_shenv is shenv:
-                cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env)
-            args = updateEnv(cmd_shenv, args)
-            if not args:
-                raise InternalShellError(j,
-                                         "Error: 'env' requires a subcommand")
+        not_args = []
+        not_count = 0
+        not_crash = False
+        while True:
+            if args[0] == 'env':
+                # Create a copy of the global environment and modify it for
+                # this one command. There might be multiple envs in a pipeline,
+                # and there might be multiple envs in a command (usually when
+                # one comes from a substitution):
+                #   env FOO=1 llc < %s | env BAR=2 llvm-mc | FileCheck %s
+                #   env FOO=1 %{another_env_plus_cmd} | FileCheck %s
+                if cmd_shenv is shenv:
+                    cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env)
+                args = updateEnv(cmd_shenv, args)
+                if not args:
+                    raise InternalShellError(j, "Error: 'env' requires a"
+                                                " subcommand")
+            elif args[0] == 'not':
+                not_args.append(args.pop(0))
+                not_count += 1
+                if args and args[0] == '--crash':
+                    not_args.append(args.pop(0))
+                    not_crash = True
+                if not args:
+                    raise InternalShellError(j, "Error: 'not' requires a"
+                                                " subcommand")
+            else:
+                break
 
         # Handle in-process builtins.
         #
@@ -655,13 +670,37 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
             if not cmd_shenv is shenv:
                 raise InternalShellError(j, "Error: 'env' cannot call '{}'"
                                             .format(args[0]))
+            if not_crash:
+                raise InternalShellError(j, "Error: 'not --crash' cannot call"
+                                            " '{}'".format(args[0]))
             if len(cmd.commands) != 1:
                 raise InternalShellError(j, "Unsupported: '{}' cannot be part"
                                             " of a pipeline".format(args[0]))
-            result = inproc_builtin(j, cmd_shenv)
+            result = inproc_builtin(Command(args, j.redirects), cmd_shenv)
+            if not_count % 2:
+                result.exitCode = int(not result.exitCode)
+            result.command.args = j.args;
             results.append(result)
             return result.exitCode
 
+        # Resolve any out-of-process builtin command before adding back 'not'
+        # commands.
+        if args[0] in builtin_commands:
+            args.insert(0, sys.executable)
+            cmd_shenv.env['PYTHONPATH'] = \
+                os.path.dirname(os.path.abspath(__file__))
+            args[1] = os.path.join(builtin_commands_dir, args[1] + ".py")
+
+        # We had to search through the 'not' commands to find all the 'env'
+        # commands and any other in-process builtin command.  We don't want to
+        # reimplement 'not' and its '--crash' here, so just push all 'not'
+        # commands back to be called as external commands.  Because this
+        # approach effectively moves all 'env' commands up front, it relies on
+        # the assumptions that (1) environment variables are not intended to be
+        # relevant to 'not' commands and (2) the 'env' command should always
+        # blindly pass along the status it receives from any command it calls.
+        args = not_args + args
+
         stdin, stdout, stderr = processRedirects(j, default_stdin, cmd_shenv,
                                                  opened_files)
 
@@ -683,17 +722,15 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
 
         # Resolve the executable path ourselves.
         executable = None
-        is_builtin_cmd = args[0] in builtin_commands;
-        if not is_builtin_cmd:
-            # For paths relative to cwd, use the cwd of the shell environment.
-            if args[0].startswith('.'):
-                exe_in_cwd = os.path.join(cmd_shenv.cwd, args[0])
-                if os.path.isfile(exe_in_cwd):
-                    executable = exe_in_cwd
-            if not executable:
-                executable = lit.util.which(args[0], cmd_shenv.env['PATH'])
-            if not executable:
-                raise InternalShellError(j, '%r: command not found' % args[0])
+        # For paths relative to cwd, use the cwd of the shell environment.
+        if args[0].startswith('.'):
+            exe_in_cwd = os.path.join(cmd_shenv.cwd, args[0])
+            if os.path.isfile(exe_in_cwd):
+                executable = exe_in_cwd
+        if not executable:
+            executable = lit.util.which(args[0], cmd_shenv.env['PATH'])
+        if not executable:
+            raise InternalShellError(j, '%r: command not found' % args[0])
 
         # Replace uses of /dev/null with temporary files.
         if kAvoidDevNull:
@@ -712,11 +749,6 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
 
         # Expand all glob expressions
         args = expand_glob_expressions(args, cmd_shenv.cwd)
-        if is_builtin_cmd:
-            args.insert(0, sys.executable)
-            cmd_shenv.env['PYTHONPATH'] = \
-                os.path.dirname(os.path.abspath(__file__))
-            args[1] = os.path.join(builtin_commands_dir ,args[1] + ".py")
 
         # On Windows, do our own command line quoting for better compatibility
         # with some core utility distributions.

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-env/env-calls-not-builtin.txt b/llvm/utils/lit/tests/Inputs/shtest-env/env-calls-not-builtin.txt
new file mode 100644
index 000000000000..b8aa57120b88
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-env/env-calls-not-builtin.txt
@@ -0,0 +1,4 @@
+# Other tests thoroughly check that 'env' cannot call various builtin commands.
+# Pick one and make sure it fails even if there's a 'not' in the way.
+
+# RUN: env -u FOO BAR=3 not rm %t.no-such-file

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/fail.py b/llvm/utils/lit/tests/Inputs/shtest-not/fail.py
new file mode 100644
index 000000000000..d64b8cb0f895
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/fail.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+import print_environment
+import sys
+
+print_environment.execute()
+sys.exit(1)

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-not/lit.cfg
new file mode 100644
index 000000000000..8609fd2c5137
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/lit.cfg
@@ -0,0 +1,7 @@
+import lit.formats
+config.name = 'shtest-not'
+config.suffixes = ['.txt']
+config.test_format = lit.formats.ShTest()
+config.test_source_root = None
+config.test_exec_root = None
+config.substitutions.append(('%{python}', '"%s"' % (sys.executable)))

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-args-last-is-crash.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-last-is-crash.txt
new file mode 100644
index 000000000000..acb4e91b74ca
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-last-is-crash.txt
@@ -0,0 +1 @@
+# RUN: not --crash

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-args-nested-none.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-nested-none.txt
new file mode 100644
index 000000000000..20fbc5f23c5a
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-nested-none.txt
@@ -0,0 +1 @@
+# RUN: not not not

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-args-none.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-none.txt
new file mode 100644
index 000000000000..101d2aecc5d7
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-args-none.txt
@@ -0,0 +1 @@
+# RUN: not

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-cd.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-cd.txt
new file mode 100644
index 000000000000..331fb51ec5d1
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-cd.txt
@@ -0,0 +1,3 @@
+# Internal cd always succeeds.
+# RUN: not not cd foobar
+# RUN: not --crash cd foobar

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-colon.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-colon.txt
new file mode 100644
index 000000000000..83bd4083d3e2
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-colon.txt
@@ -0,0 +1,3 @@
+# ":" always succeeds.
+# RUN: not not : foobar
+# RUN: not --crash :

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff -with-crash.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff -with-crash.txt
new file mode 100644
index 000000000000..df721275cb0b
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff -with-crash.txt
@@ -0,0 +1,6 @@
+# Lit's 
diff  is out-of-process, so check that "not --crash 
diff " fails because
+# 
diff  doesn't crash rather than because "not --crash 
diff " isn't supported.
+
+# RUN: echo 'foo' > %t.foo
+# RUN: echo 'bar' > %t.bar
+# RUN: not --crash 
diff  -u %t.foo %t.bar

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff .txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff .txt
new file mode 100644
index 000000000000..d16ce75acbe9
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-
diff .txt
@@ -0,0 +1,16 @@
+# RUN: echo 'foo' > %t.foo0
+# RUN: echo 'foo' > %t.foo1
+# RUN: echo 'bar' > %t.bar
+
+# 
diff  fails.
+# RUN: not 
diff  %t.foo0 %t.bar
+# RUN: not not not 
diff  %t.foo0 %t.bar
+# RUN: not not not not not 
diff  %t.foo0 %t.bar
+
+# 
diff  succeeds.
+# RUN: 
diff  %t.foo0 %t.foo1
+# RUN: not not 
diff  %t.foo0 %t.foo1
+# RUN: not not not not 
diff  %t.foo0 %t.foo1
+
+# 
diff  succeeds but we expect failure.
+# RUN: not 
diff  %t.foo0 %t.foo1

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-echo.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-echo.txt
new file mode 100644
index 000000000000..b96da29d4834
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-echo.txt
@@ -0,0 +1,3 @@
+# Internal "echo" always succeeds.
+# RUN: not not echo hello world
+# RUN: not --crash echo hello world

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-env-builtin.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-env-builtin.txt
new file mode 100644
index 000000000000..68aa2974bd53
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-env-builtin.txt
@@ -0,0 +1,4 @@
+# Other tests thoroughly check that 'not' cannot call various builtin commands.
+# Pick one and make sure it fails even if there's an 'env' in the way.
+
+# RUN: not --crash env -u FOO BAR=3 rm %t.no-such-file

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-export.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-export.txt
new file mode 100644
index 000000000000..13d0fe066151
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-export.txt
@@ -0,0 +1,3 @@
+# Internal "export" always succeeds.
+# RUN: not not export FOO=1
+# RUN: not --crash export BAZ=3

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-external.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-external.txt
new file mode 100644
index 000000000000..9209da83d7d8
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-external.txt
@@ -0,0 +1,66 @@
+# RUN: echo foo > %t.in
+# RUN: echo bar >> %t.in
+
+
+# Simple uses of 'not'
+
+# RUN: not %{python} fail.py
+# RUN: not not %{python} pass.py
+# RUN: not not not %{python} fail.py
+# RUN: not not not not %{python} pass.py
+
+
+# Simple uses of 'not --crash'
+
+# RUN: not not --crash %{python} pass.py
+# RUN: not not --crash %{python} fail.py
+# RUN: not not --crash not %{python} pass.py
+# RUN: not not --crash not  %{python} fail.py
+
+
+# Various patterns of 'not' and 'env'
+#
+# There's no particular pattern to the 'env' arguments except we try not to
+# do the same thing every time.
+
+# RUN: env not %{python} fail.py | FileCheck -check-prefixes=FOO-NO,BAR-NO %s
+# RUN: not env %{python} fail.py | FileCheck -check-prefixes=FOO-NO,BAR-NO %s
+
+# RUN: env FOO=1 not %{python} fail.py \
+# RUN: | FileCheck -check-prefixes=FOO1,BAR-NO %s
+
+# RUN: not env FOO=1 BAR=1 %{python} fail.py \
+# RUN: | FileCheck -check-prefixes=FOO1,BAR1 %s
+
+# RUN: env FOO=1 BAR=1 not env -u FOO BAR=2 %{python} fail.py \
+# RUN: | FileCheck -check-prefixes=FOO-NO,BAR2 %s
+
+# RUN: not env FOO=1 BAR=1 not env -u FOO -u BAR %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO-NO,BAR-NO %s
+
+# RUN: not not env FOO=1 env FOO=2 BAR=1 %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO2,BAR1 %s
+
+# RUN: env FOO=1 -u BAR env -u FOO BAR=1 not not %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO-NO,BAR1 %s
+
+
+# Various patterns of 'not', 'not --crash', and 'env'
+
+# RUN: not env FOO=1 BAR=1 env FOO=2 BAR=2 not --crash %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO2,BAR2 %s
+
+# RUN: not env FOO=1 BAR=1 not --crash not %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO1,BAR1 %s
+
+# RUN: not not --crash env -u BAR not env -u FOO BAR=1 %{python} pass.py \
+# RUN: | FileCheck -check-prefixes=FOO-NO,BAR1 %s
+
+
+# FOO-NO: FOO = [undefined]
+# FOO1:   FOO = 1
+# FOO2:   FOO = 2
+
+# BAR-NO: BAR = [undefined]
+# BAR1:   BAR = 1
+# BAR2:   BAR = 2

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-mkdir.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-mkdir.txt
new file mode 100644
index 000000000000..262d0a71c2d4
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-mkdir.txt
@@ -0,0 +1,2 @@
+# RUN: not mkdir %t/foobar
+# RUN: not --crash mkdir foobar

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-rm.txt b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-rm.txt
new file mode 100644
index 000000000000..20660ddd3c34
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/not-calls-rm.txt
@@ -0,0 +1,2 @@
+# RUN: not rm %t
+# RUN: not --crash rm foobar

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/pass.py b/llvm/utils/lit/tests/Inputs/shtest-not/pass.py
new file mode 100644
index 000000000000..bd113596b7db
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/pass.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+import print_environment
+
+print_environment.execute()

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-not/print_environment.py b/llvm/utils/lit/tests/Inputs/shtest-not/print_environment.py
new file mode 100644
index 000000000000..7397889d5e76
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-not/print_environment.py
@@ -0,0 +1,6 @@
+from __future__ import print_function
+import os
+
+def execute():
+    for name in ['FOO', 'BAR']:
+        print(name, '=', os.environ.get(name, '[undefined]'))

diff  --git a/llvm/utils/lit/tests/shtest-env.py b/llvm/utils/lit/tests/shtest-env.py
index 9eee63abe0e1..28a7639c3b02 100644
--- a/llvm/utils/lit/tests/shtest-env.py
+++ b/llvm/utils/lit/tests/shtest-env.py
@@ -7,7 +7,7 @@
 
 # Make sure env commands are included in printed commands.
 
-# CHECK: -- Testing: 15 tests{{.*}}
+# CHECK: -- Testing: 16 tests{{.*}}
 
 # CHECK: FAIL: shtest-env :: env-args-last-is-assign.txt ({{[^)]*}})
 # CHECK: $ "env" "FOO=1"
@@ -67,6 +67,11 @@
 # CHECK: Error: 'env' cannot call 'mkdir'
 # CHECK: error: command failed with exit status: {{.*}}
 
+# CHECK: FAIL: shtest-env :: env-calls-not-builtin.txt ({{[^)]*}})
+# CHECK: $ "env" "-u" "FOO" "BAR=3" "not" "rm" "{{.*}}.no-such-file"
+# CHECK: Error: 'env' cannot call 'rm'
+# CHECK: error: command failed with exit status: {{.*}}
+
 # CHECK: FAIL: shtest-env :: env-calls-rm.txt ({{[^)]*}})
 # CHECK: $ "env" "-u" "FOO" "BAR=3" "rm" "foobar"
 # CHECK: Error: 'env' cannot call 'rm'
@@ -89,5 +94,5 @@
 # CHECK-NOT: ${{.*}}print_environment.py
 
 # CHECK: Expected Passes : 4
-# CHECK: Unexpected Failures: 11
+# CHECK: Unexpected Failures: 12
 # CHECK-NOT: {{.}}

diff  --git a/llvm/utils/lit/tests/shtest-not.py b/llvm/utils/lit/tests/shtest-not.py
new file mode 100644
index 000000000000..bd204685ebca
--- /dev/null
+++ b/llvm/utils/lit/tests/shtest-not.py
@@ -0,0 +1,115 @@
+# Check the not command
+#
+# RUN: not %{lit} -j 1 -a -v %{inputs}/shtest-not \
+# RUN: | FileCheck -match-full-lines %s
+#
+# END.
+
+# Make sure not and env commands are included in printed commands.
+
+# CHECK: -- Testing: 13 tests{{.*}}
+
+# CHECK: FAIL: shtest-not :: not-args-last-is-crash.txt {{.*}}
+# CHECK: $ "not" "--crash"
+# CHECK: Error: 'not' requires a subcommand
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-args-nested-none.txt {{.*}}
+# CHECK: $ "not" "not" "not"
+# CHECK: Error: 'not' requires a subcommand
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-args-none.txt {{.*}}
+# CHECK: $ "not"
+# CHECK: Error: 'not' requires a subcommand
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-cd.txt {{.*}}
+# CHECK: $ "not" "not" "cd" "foobar"
+# CHECK: $ "not" "--crash" "cd" "foobar"
+# CHECK: Error: 'not --crash' cannot call 'cd'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-colon.txt {{.*}}
+# CHECK: $ "not" "not" ":" "foobar"
+# CHECK: $ "not" "--crash" ":"
+# CHECK: Error: 'not --crash' cannot call ':'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-
diff -with-crash.txt {{.*}}
+# CHECK: $ "not" "--crash" "
diff " "-u" {{.*}}
+# CHECK-NOT: "$"
+# CHECK-NOT: {{[Ee]rror}}
+# CHECK: error: command failed with exit status: {{.*}}
+# CHECK-NOT: {{[Ee]rror}}
+# CHECK-NOT: "$"
+
+# CHECK: FAIL: shtest-not :: not-calls-
diff .txt {{.*}}
+# CHECK: $ "not" "
diff " {{.*}}
+# CHECK: $ "not" "not" "not" "
diff " {{.*}}
+# CHECK: $ "not" "not" "not" "not" "not" "
diff " {{.*}}
+# CHECK: $ "
diff " {{.*}}
+# CHECK: $ "not" "not" "
diff " {{.*}}
+# CHECK: $ "not" "not" "not" "not" "
diff " {{.*}}
+# CHECK: $ "not" "
diff " {{.*}}
+# CHECK-NOT: "$"
+
+# CHECK: FAIL: shtest-not :: not-calls-echo.txt {{.*}}
+# CHECK: $ "not" "not" "echo" "hello" "world"
+# CHECK: $ "not" "--crash" "echo" "hello" "world"
+# CHECK: Error: 'not --crash' cannot call 'echo'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-env-builtin.txt {{.*}}
+# CHECK: $ "not" "--crash" "env" "-u" "FOO" "BAR=3" "rm" "{{.*}}.no-such-file"
+# CHECK: Error: 'env' cannot call 'rm'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-export.txt {{.*}}
+# CHECK: $ "not" "not" "export" "FOO=1"
+# CHECK: $ "not" "--crash" "export" "BAZ=3"
+# CHECK: Error: 'not --crash' cannot call 'export'
+# CHECK: error: command failed with exit status: {{.*}}
+
+
+# CHECK: PASS: shtest-not :: not-calls-external.txt {{.*}}
+
+# CHECK: $ "not" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "not" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "not" "not" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "not" "not" "not" "{{[^"]*}}" "pass.py"
+
+# CHECK: $ "not" "not" "--crash" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "not" "--crash" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "not" "--crash" "not" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "not" "--crash" "not" "{{[^"]*}}" "fail.py"
+
+# CHECK: $ "env" "not" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "env" "{{[^"]*}}" "fail.py"
+# CHECK: $ "env" "FOO=1" "not" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "env" "FOO=1" "BAR=1" "{{[^"]*}}" "fail.py"
+# CHECK: $ "env" "FOO=1" "BAR=1" "not" "env" "-u" "FOO" "BAR=2" "{{[^"]*}}" "fail.py"
+# CHECK: $ "not" "env" "FOO=1" "BAR=1" "not" "env" "-u" "FOO" "-u" "BAR" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "not" "env" "FOO=1" "env" "FOO=2" "BAR=1" "{{[^"]*}}" "pass.py"
+# CHECK: $ "env" "FOO=1" "-u" "BAR" "env" "-u" "FOO" "BAR=1" "not" "not" "{{[^"]*}}" "pass.py"
+
+# CHECK: $ "not" "env" "FOO=1" "BAR=1" "env" "FOO=2" "BAR=2" "not" "--crash" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "env" "FOO=1" "BAR=1" "not" "--crash" "not" "{{[^"]*}}" "pass.py"
+# CHECK: $ "not" "not" "--crash" "env" "-u" "BAR" "not" "env" "-u" "FOO" "BAR=1" "{{[^"]*}}" "pass.py"
+
+
+# CHECK: FAIL: shtest-not :: not-calls-mkdir.txt {{.*}}
+# CHECK: $ "not" "mkdir" {{.*}}
+# CHECK: $ "not" "--crash" "mkdir" "foobar"
+# CHECK: Error: 'not --crash' cannot call 'mkdir'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: FAIL: shtest-not :: not-calls-rm.txt {{.*}}
+# CHECK: $ "not" "rm" {{.*}}
+# CHECK: $ "not" "--crash" "rm" "foobar"
+# CHECK: Error: 'not --crash' cannot call 'rm'
+# CHECK: error: command failed with exit status: {{.*}}
+
+# CHECK: Expected Passes : 1
+# CHECK: Unexpected Failures: 12
+# CHECK-NOT: {{.}}


        


More information about the llvm-commits mailing list