[lit] Handle plain negations directly in the internal shell
authorMartin Storsjö <martin@martin.st>
Thu, 18 Mar 2021 07:44:01 +0000 (09:44 +0200)
committerMartin Storsjö <martin@martin.st>
Fri, 19 Mar 2021 07:33:26 +0000 (09:33 +0200)
Keep running "not --crash" via the external "not" executable, but
for plain negations, and for cases that use the shell "!" operator,
just skip that argument and invert the return code.

The libcxx tests only use the shell operator "!" for negations,
never the "not" executable, because libcxx tests can be run without
having a fully built llvm tree available providing the "not"
executable.

This allows using the internal shell for libcxx tests.

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

llvm/utils/lit/lit/TestRunner.py

index f826bc9..820cbce 100644 (file)
@@ -608,6 +608,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
     assert isinstance(cmd, ShUtil.Pipeline)
 
     procs = []
+    negate_procs = []
     default_stdin = subprocess.PIPE
     stderrTempFiles = []
     opened_files = []
@@ -653,6 +654,12 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
                 if not args:
                     raise InternalShellError(j, "Error: 'not' requires a"
                                                 " subcommand")
+            elif args[0] == '!':
+                not_args.append(args.pop(0))
+                not_count += 1
+                if not args:
+                    raise InternalShellError(j, "Error: '!' requires a"
+                                                " subcommand")
             else:
                 break
 
@@ -699,7 +706,15 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
         # 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
+
+        # For plain negations, either 'not' without '--crash', or the shell
+        # operator '!', leave them out from the command to execute and
+        # invert the result code afterwards.
+        if not_crash:
+            args = not_args + args
+            not_count = 0
+        else:
+            not_args = []
 
         stdin, stdout, stderr = processRedirects(j, default_stdin, cmd_shenv,
                                                  opened_files)
@@ -763,6 +778,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
                                           stderr = stderr,
                                           env = cmd_shenv.env,
                                           close_fds = kUseCloseFDs))
+            negate_procs.append((not_count % 2) != 0)
             # Let the helper know about this process
             timeoutHelper.addProcess(procs[-1])
         except OSError as e:
@@ -815,6 +831,8 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
         # Detect Ctrl-C in subprocess.
         if res == -signal.SIGINT:
             raise KeyboardInterrupt
+        if negate_procs[i]:
+            res = not res
 
         # Ensure the resulting output is always of string type.
         try: