From 80b7aace9f29deb93532c0b2ac1376dc1d0e3958 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Thu, 17 Oct 2019 14:02:42 +0000 Subject: [PATCH] [lit] Make internal diff work in pipelines When using lit's internal shell, RUN lines like the following accidentally execute an external `diff` instead of lit's internal `diff`: ``` # RUN: program | diff file - # RUN: not diff file1 file2 | FileCheck %s ``` Such cases exist now, in `clang/test/Analysis` for example. We are preparing patches to ensure lit's internal `diff` is called in such cases, which will then fail because lit's internal `diff` cannot currently be used in pipelines and doesn't recognize `-` as a command-line option. To enable pipelines, this patch moves lit's `diff` implementation into an out-of-process script, similar to lit's `cat` implementation. A follow-up patch will implement `-` to mean stdin. Reviewed By: probinson, stella.stamenova Differential Revision: https://reviews.llvm.org/D66574 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375114 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/lit/lit/TestRunner.py | 231 +---------------- utils/lit/lit/builtin_commands/diff.py | 236 ++++++++++++++++++ .../Inputs/shtest-shell/diff-error-0.txt | 3 - .../tests/Inputs/shtest-shell/diff-pipes.txt | 15 ++ .../shtest-shell/diff-unified-error-0.txt | 3 - .../shtest-shell/diff-unified-error-1.txt | 3 - .../Inputs/shtest-shell/diff-unified.txt | 4 + utils/lit/tests/max-failures.py | 2 +- utils/lit/tests/shtest-shell.py | 78 +++--- 9 files changed, 304 insertions(+), 271 deletions(-) create mode 100644 utils/lit/lit/builtin_commands/diff.py delete mode 100644 utils/lit/tests/Inputs/shtest-shell/diff-error-0.txt create mode 100644 utils/lit/tests/Inputs/shtest-shell/diff-pipes.txt delete mode 100644 utils/lit/tests/Inputs/shtest-shell/diff-unified-error-0.txt delete mode 100644 utils/lit/tests/Inputs/shtest-shell/diff-unified-error-1.txt diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index f1447809c98..a334d0d638e 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -1,11 +1,8 @@ from __future__ import absolute_import -import difflib import errno -import functools import io import itertools import getopt -import locale import os, signal, subprocess, sys import re import stat @@ -362,222 +359,6 @@ def executeBuiltinMkdir(cmd, cmd_shenv): exitCode = 1 return ShellCommandResult(cmd, "", stderr.getvalue(), exitCode, False) -def executeBuiltinDiff(cmd, cmd_shenv): - """executeBuiltinDiff - Compare files line by line.""" - args = expand_glob_expressions(cmd.args, cmd_shenv.cwd)[1:] - try: - opts, args = getopt.gnu_getopt(args, "wbuU:r", ["strip-trailing-cr"]) - except getopt.GetoptError as err: - raise InternalShellError(cmd, "Unsupported: 'diff': %s" % str(err)) - - filelines, filepaths, dir_trees = ([] for i in range(3)) - ignore_all_space = False - ignore_space_change = False - unified_diff = False - num_context_lines = 3 - recursive_diff = False - strip_trailing_cr = False - for o, a in opts: - if o == "-w": - ignore_all_space = True - elif o == "-b": - ignore_space_change = True - elif o == "-u": - unified_diff = True - elif o.startswith("-U"): - unified_diff = True - try: - num_context_lines = int(a) - if num_context_lines < 0: - raise ValueException - except: - raise InternalShellError(cmd, - "Error: invalid '-U' argument: {}\n" - .format(a)) - elif o == "-r": - recursive_diff = True - elif o == "--strip-trailing-cr": - strip_trailing_cr = True - else: - assert False, "unhandled option" - - if len(args) != 2: - raise InternalShellError(cmd, "Error: missing or extra operand") - - def getDirTree(path, basedir=""): - # Tree is a tuple of form (dirname, child_trees). - # An empty dir has child_trees = [], a file has child_trees = None. - child_trees = [] - for dirname, child_dirs, files in os.walk(os.path.join(basedir, path)): - for child_dir in child_dirs: - child_trees.append(getDirTree(child_dir, dirname)) - for filename in files: - child_trees.append((filename, None)) - return path, sorted(child_trees) - - def compareTwoFiles(filepaths): - filelines = [] - for file in filepaths: - with open(file, 'rb') as file_bin: - filelines.append(file_bin.readlines()) - - try: - return compareTwoTextFiles(filepaths, filelines, - locale.getpreferredencoding(False)) - except UnicodeDecodeError: - try: - return compareTwoTextFiles(filepaths, filelines, "utf-8") - except: - return compareTwoBinaryFiles(filepaths, filelines) - - def compareTwoBinaryFiles(filepaths, filelines): - exitCode = 0 - if hasattr(difflib, 'diff_bytes'): - # python 3.5 or newer - diffs = difflib.diff_bytes(difflib.unified_diff, filelines[0], - filelines[1], filepaths[0].encode(), - filepaths[1].encode(), - n = num_context_lines) - diffs = [diff.decode(errors="backslashreplace") for diff in diffs] - else: - # python 2.7 - func = difflib.unified_diff if unified_diff else difflib.context_diff - diffs = func(filelines[0], filelines[1], filepaths[0], filepaths[1], - n = num_context_lines) - - for diff in diffs: - stdout.write(to_string(diff)) - exitCode = 1 - return exitCode - - def compareTwoTextFiles(filepaths, filelines_bin, encoding): - filelines = [] - for lines_bin in filelines_bin: - lines = [] - for line_bin in lines_bin: - line = line_bin.decode(encoding=encoding) - lines.append(line) - filelines.append(lines) - - exitCode = 0 - def compose2(f, g): - return lambda x: f(g(x)) - - f = lambda x: x - if strip_trailing_cr: - f = compose2(lambda line: line.replace('\r\n', '\n'), f) - if ignore_all_space or ignore_space_change: - ignoreSpace = lambda line, separator: separator.join(line.split()) - ignoreAllSpaceOrSpaceChange = functools.partial(ignoreSpace, separator='' if ignore_all_space else ' ') - f = compose2(ignoreAllSpaceOrSpaceChange, f) - - for idx, lines in enumerate(filelines): - filelines[idx]= [f(line) for line in lines] - - func = difflib.unified_diff if unified_diff else difflib.context_diff - for diff in func(filelines[0], filelines[1], filepaths[0], filepaths[1], - n = num_context_lines): - stdout.write(to_string(diff)) - exitCode = 1 - return exitCode - - def printDirVsFile(dir_path, file_path): - if os.path.getsize(file_path): - msg = "File %s is a directory while file %s is a regular file" - else: - msg = "File %s is a directory while file %s is a regular empty file" - stdout.write(msg % (dir_path, file_path) + "\n") - - def printFileVsDir(file_path, dir_path): - if os.path.getsize(file_path): - msg = "File %s is a regular file while file %s is a directory" - else: - msg = "File %s is a regular empty file while file %s is a directory" - stdout.write(msg % (file_path, dir_path) + "\n") - - def printOnlyIn(basedir, path, name): - stdout.write("Only in %s: %s\n" % (os.path.join(basedir, path), name)) - - def compareDirTrees(dir_trees, base_paths=["", ""]): - # Dirnames of the trees are not checked, it's caller's responsibility, - # as top-level dirnames are always different. Base paths are important - # for doing os.walk, but we don't put it into tree's dirname in order - # to speed up string comparison below and while sorting in getDirTree. - left_tree, right_tree = dir_trees[0], dir_trees[1] - left_base, right_base = base_paths[0], base_paths[1] - - # Compare two files or report file vs. directory mismatch. - if left_tree[1] is None and right_tree[1] is None: - return compareTwoFiles([os.path.join(left_base, left_tree[0]), - os.path.join(right_base, right_tree[0])]) - - if left_tree[1] is None and right_tree[1] is not None: - printFileVsDir(os.path.join(left_base, left_tree[0]), - os.path.join(right_base, right_tree[0])) - return 1 - - if left_tree[1] is not None and right_tree[1] is None: - printDirVsFile(os.path.join(left_base, left_tree[0]), - os.path.join(right_base, right_tree[0])) - return 1 - - # Compare two directories via recursive use of compareDirTrees. - exitCode = 0 - left_names = [node[0] for node in left_tree[1]] - right_names = [node[0] for node in right_tree[1]] - l, r = 0, 0 - while l < len(left_names) and r < len(right_names): - # Names are sorted in getDirTree, rely on that order. - if left_names[l] < right_names[r]: - exitCode = 1 - printOnlyIn(left_base, left_tree[0], left_names[l]) - l += 1 - elif left_names[l] > right_names[r]: - exitCode = 1 - printOnlyIn(right_base, right_tree[0], right_names[r]) - r += 1 - else: - exitCode |= compareDirTrees([left_tree[1][l], right_tree[1][r]], - [os.path.join(left_base, left_tree[0]), - os.path.join(right_base, right_tree[0])]) - l += 1 - r += 1 - - # At least one of the trees has ended. Report names from the other tree. - while l < len(left_names): - exitCode = 1 - printOnlyIn(left_base, left_tree[0], left_names[l]) - l += 1 - while r < len(right_names): - exitCode = 1 - printOnlyIn(right_base, right_tree[0], right_names[r]) - r += 1 - return exitCode - - stderr = StringIO() - stdout = StringIO() - exitCode = 0 - try: - for file in args: - if not os.path.isabs(file): - file = os.path.realpath(os.path.join(cmd_shenv.cwd, file)) - - if recursive_diff: - dir_trees.append(getDirTree(file)) - else: - filepaths.append(file) - - if not recursive_diff: - exitCode = compareTwoFiles(filepaths) - else: - exitCode = compareDirTrees(dir_trees) - - except IOError as err: - stderr.write("Error: 'diff' command failed, %s\n" % str(err)) - exitCode = 1 - - return ShellCommandResult(cmd, stdout.getvalue(), stderr.getvalue(), exitCode, False) - def executeBuiltinRm(cmd, cmd_shenv): """executeBuiltinRm - Removes (deletes) files or directories.""" args = expand_glob_expressions(cmd.args, cmd_shenv.cwd)[1:] @@ -843,14 +624,6 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper): results.append(cmdResult) return cmdResult.exitCode - if cmd.commands[0].args[0] == 'diff': - if len(cmd.commands) != 1: - raise InternalShellError(cmd.commands[0], "Unsupported: 'diff' " - "cannot be part of a pipeline") - cmdResult = executeBuiltinDiff(cmd.commands[0], shenv) - results.append(cmdResult) - return cmdResult.exitCode - if cmd.commands[0].args[0] == 'rm': if len(cmd.commands) != 1: raise InternalShellError(cmd.commands[0], "Unsupported: 'rm' " @@ -871,7 +644,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper): stderrTempFiles = [] opened_files = [] named_temp_files = [] - builtin_commands = set(['cat']) + builtin_commands = set(['cat', 'diff']) builtin_commands_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "builtin_commands") # To avoid deadlock, we use a single stderr stream for piped # output. This is null until we have seen some output using @@ -942,6 +715,8 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper): 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 diff --git a/utils/lit/lit/builtin_commands/diff.py b/utils/lit/lit/builtin_commands/diff.py new file mode 100644 index 00000000000..33895b71db6 --- /dev/null +++ b/utils/lit/lit/builtin_commands/diff.py @@ -0,0 +1,236 @@ +import difflib +import functools +import getopt +import locale +import os +import sys + +import util +from util import to_string + +class DiffFlags(): + def __init__(self): + self.ignore_all_space = False + self.ignore_space_change = False + self.unified_diff = False + self.num_context_lines = 3 + self.recursive_diff = False + self.strip_trailing_cr = False + +def getDirTree(path, basedir=""): + # Tree is a tuple of form (dirname, child_trees). + # An empty dir has child_trees = [], a file has child_trees = None. + child_trees = [] + for dirname, child_dirs, files in os.walk(os.path.join(basedir, path)): + for child_dir in child_dirs: + child_trees.append(getDirTree(child_dir, dirname)) + for filename in files: + child_trees.append((filename, None)) + return path, sorted(child_trees) + +def compareTwoFiles(flags, filepaths): + filelines = [] + for file in filepaths: + with open(file, 'rb') as file_bin: + filelines.append(file_bin.readlines()) + + try: + return compareTwoTextFiles(flags, filepaths, filelines, + locale.getpreferredencoding(False)) + except UnicodeDecodeError: + try: + return compareTwoTextFiles(flags, filepaths, filelines, "utf-8") + except: + return compareTwoBinaryFiles(flags, filepaths, filelines) + +def compareTwoBinaryFiles(flags, filepaths, filelines): + exitCode = 0 + if hasattr(difflib, 'diff_bytes'): + # python 3.5 or newer + diffs = difflib.diff_bytes(difflib.unified_diff, filelines[0], + filelines[1], filepaths[0].encode(), + filepaths[1].encode(), + n = flags.num_context_lines) + diffs = [diff.decode(errors="backslashreplace") for diff in diffs] + else: + # python 2.7 + if flags.unified_diff: + func = difflib.unified_diff + else: + func = difflib.context_diff + diffs = func(filelines[0], filelines[1], filepaths[0], filepaths[1], + n = flags.num_context_lines) + + for diff in diffs: + sys.stdout.write(to_string(diff)) + exitCode = 1 + return exitCode + +def compareTwoTextFiles(flags, filepaths, filelines_bin, encoding): + filelines = [] + for lines_bin in filelines_bin: + lines = [] + for line_bin in lines_bin: + line = line_bin.decode(encoding=encoding) + lines.append(line) + filelines.append(lines) + + exitCode = 0 + def compose2(f, g): + return lambda x: f(g(x)) + + f = lambda x: x + if flags.strip_trailing_cr: + f = compose2(lambda line: line.replace('\r\n', '\n'), f) + if flags.ignore_all_space or flags.ignore_space_change: + ignoreSpace = lambda line, separator: separator.join(line.split()) + ignoreAllSpaceOrSpaceChange = functools.partial(ignoreSpace, separator='' if flags.ignore_all_space else ' ') + f = compose2(ignoreAllSpaceOrSpaceChange, f) + + for idx, lines in enumerate(filelines): + filelines[idx]= [f(line) for line in lines] + + func = difflib.unified_diff if flags.unified_diff else difflib.context_diff + for diff in func(filelines[0], filelines[1], filepaths[0], filepaths[1], + n = flags.num_context_lines): + sys.stdout.write(to_string(diff)) + exitCode = 1 + return exitCode + +def printDirVsFile(dir_path, file_path): + if os.path.getsize(file_path): + msg = "File %s is a directory while file %s is a regular file" + else: + msg = "File %s is a directory while file %s is a regular empty file" + sys.stdout.write(msg % (dir_path, file_path) + "\n") + +def printFileVsDir(file_path, dir_path): + if os.path.getsize(file_path): + msg = "File %s is a regular file while file %s is a directory" + else: + msg = "File %s is a regular empty file while file %s is a directory" + sys.stdout.write(msg % (file_path, dir_path) + "\n") + +def printOnlyIn(basedir, path, name): + sys.stdout.write("Only in %s: %s\n" % (os.path.join(basedir, path), name)) + +def compareDirTrees(flags, dir_trees, base_paths=["", ""]): + # Dirnames of the trees are not checked, it's caller's responsibility, + # as top-level dirnames are always different. Base paths are important + # for doing os.walk, but we don't put it into tree's dirname in order + # to speed up string comparison below and while sorting in getDirTree. + left_tree, right_tree = dir_trees[0], dir_trees[1] + left_base, right_base = base_paths[0], base_paths[1] + + # Compare two files or report file vs. directory mismatch. + if left_tree[1] is None and right_tree[1] is None: + return compareTwoFiles(flags, + [os.path.join(left_base, left_tree[0]), + os.path.join(right_base, right_tree[0])]) + + if left_tree[1] is None and right_tree[1] is not None: + printFileVsDir(os.path.join(left_base, left_tree[0]), + os.path.join(right_base, right_tree[0])) + return 1 + + if left_tree[1] is not None and right_tree[1] is None: + printDirVsFile(os.path.join(left_base, left_tree[0]), + os.path.join(right_base, right_tree[0])) + return 1 + + # Compare two directories via recursive use of compareDirTrees. + exitCode = 0 + left_names = [node[0] for node in left_tree[1]] + right_names = [node[0] for node in right_tree[1]] + l, r = 0, 0 + while l < len(left_names) and r < len(right_names): + # Names are sorted in getDirTree, rely on that order. + if left_names[l] < right_names[r]: + exitCode = 1 + printOnlyIn(left_base, left_tree[0], left_names[l]) + l += 1 + elif left_names[l] > right_names[r]: + exitCode = 1 + printOnlyIn(right_base, right_tree[0], right_names[r]) + r += 1 + else: + exitCode |= compareDirTrees(flags, + [left_tree[1][l], right_tree[1][r]], + [os.path.join(left_base, left_tree[0]), + os.path.join(right_base, right_tree[0])]) + l += 1 + r += 1 + + # At least one of the trees has ended. Report names from the other tree. + while l < len(left_names): + exitCode = 1 + printOnlyIn(left_base, left_tree[0], left_names[l]) + l += 1 + while r < len(right_names): + exitCode = 1 + printOnlyIn(right_base, right_tree[0], right_names[r]) + r += 1 + return exitCode + +def main(argv): + args = argv[1:] + try: + opts, args = getopt.gnu_getopt(args, "wbuU:r", ["strip-trailing-cr"]) + except getopt.GetoptError as err: + sys.stderr.write("Unsupported: 'diff': %s\n" % str(err)) + sys.exit(1) + + flags = DiffFlags() + filelines, filepaths, dir_trees = ([] for i in range(3)) + for o, a in opts: + if o == "-w": + flags.ignore_all_space = True + elif o == "-b": + flags.ignore_space_change = True + elif o == "-u": + flags.unified_diff = True + elif o.startswith("-U"): + flags.unified_diff = True + try: + flags.num_context_lines = int(a) + if flags.num_context_lines < 0: + raise ValueException + except: + sys.stderr.write("Error: invalid '-U' argument: {}\n" + .format(a)) + sys.exit(1) + elif o == "-r": + flags.recursive_diff = True + elif o == "--strip-trailing-cr": + flags.strip_trailing_cr = True + else: + assert False, "unhandled option" + + if len(args) != 2: + sys.stderr.write("Error: missing or extra operand\n") + sys.exit(1) + + exitCode = 0 + try: + for file in args: + if not os.path.isabs(file): + file = os.path.realpath(os.path.join(os.getcwd(), file)) + + if flags.recursive_diff: + dir_trees.append(getDirTree(file)) + else: + filepaths.append(file) + + if not flags.recursive_diff: + exitCode = compareTwoFiles(flags, filepaths) + else: + exitCode = compareDirTrees(flags, dir_trees) + + except IOError as err: + sys.stderr.write("Error: 'diff' command failed, %s\n" % str(err)) + exitCode = 1 + + sys.exit(exitCode) + +if __name__ == "__main__": + main(sys.argv) diff --git a/utils/lit/tests/Inputs/shtest-shell/diff-error-0.txt b/utils/lit/tests/Inputs/shtest-shell/diff-error-0.txt deleted file mode 100644 index 81888cf8197..00000000000 --- a/utils/lit/tests/Inputs/shtest-shell/diff-error-0.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Check error on a unsupported diff (cannot be part of a pipeline). -# -# RUN: diff diff-error-0.txt diff-error-0.txt | echo Output diff --git a/utils/lit/tests/Inputs/shtest-shell/diff-pipes.txt b/utils/lit/tests/Inputs/shtest-shell/diff-pipes.txt new file mode 100644 index 00000000000..ce0abca1661 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/diff-pipes.txt @@ -0,0 +1,15 @@ +# RUN: echo foo > %t.foo +# RUN: echo bar > %t.bar + +# Check output pipe. +# RUN: diff %t.foo %t.foo | FileCheck -allow-empty -check-prefix=EMPTY %s +# RUN: diff -u %t.foo %t.bar | FileCheck %s && false || true + +# Fail so lit will print output. +# RUN: false + +# CHECK: @@ +# CHECK-NEXT: -foo +# CHECK-NEXT: +bar + +# EMPTY-NOT: {{.}} diff --git a/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-0.txt b/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-0.txt deleted file mode 100644 index ee3858a02ba..00000000000 --- a/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-0.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Check bad -U argument. -# RUN: echo foo > %t -# RUN: diff -U 30.1 %t %t diff --git a/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-1.txt b/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-1.txt deleted file mode 100644 index e46e8b5783b..00000000000 --- a/utils/lit/tests/Inputs/shtest-shell/diff-unified-error-1.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Check bad -U argument. -# RUN: echo foo > %t -# RUN: diff -U-1 %t %t diff --git a/utils/lit/tests/Inputs/shtest-shell/diff-unified.txt b/utils/lit/tests/Inputs/shtest-shell/diff-unified.txt index a6a7eef3f9b..e977c193247 100644 --- a/utils/lit/tests/Inputs/shtest-shell/diff-unified.txt +++ b/utils/lit/tests/Inputs/shtest-shell/diff-unified.txt @@ -30,5 +30,9 @@ # RUN: diff -U4 %t.foo %t.bar && false || true # RUN: diff -U0 %t.foo %t.bar && false || true +# Check bad -U argument. +# RUN: diff -U 30.1 %t.foo %t.foo && false || true +# RUN: diff -U-1 %t.foo %t.foo && false || true + # Fail so lit will print output. # RUN: false diff --git a/utils/lit/tests/max-failures.py b/utils/lit/tests/max-failures.py index 6ad37533692..7bd5c32e72e 100644 --- a/utils/lit/tests/max-failures.py +++ b/utils/lit/tests/max-failures.py @@ -8,7 +8,7 @@ # # END. -# CHECK: Failing Tests (32) +# CHECK: Failing Tests (30) # CHECK: Failing Tests (1) # CHECK: Failing Tests (2) # CHECK: error: argument --max-failures: requires positive integer, but found '0' diff --git a/utils/lit/tests/shtest-shell.py b/utils/lit/tests/shtest-shell.py index 1fc8b30c7ee..dd5bfbe30f6 100644 --- a/utils/lit/tests/shtest-shell.py +++ b/utils/lit/tests/shtest-shell.py @@ -86,28 +86,20 @@ # CHECK: *** -# CHECK: FAIL: shtest-shell :: diff-error-0.txt -# CHECK: *** TEST 'shtest-shell :: diff-error-0.txt' FAILED *** -# CHECK: $ "diff" "diff-error-0.txt" "diff-error-0.txt" -# CHECK: # command stderr: -# CHECK: Unsupported: 'diff' cannot be part of a pipeline -# CHECK: error: command failed with exit status: 127 -# CHECK: *** - # CHECK: FAIL: shtest-shell :: diff-error-1.txt # CHECK: *** TEST 'shtest-shell :: diff-error-1.txt' FAILED *** # CHECK: $ "diff" "-B" "temp1.txt" "temp2.txt" # CHECK: # command stderr: # CHECK: Unsupported: 'diff': option -B not recognized -# CHECK: error: command failed with exit status: 127 +# CHECK: error: command failed with exit status: 1 # CHECK: *** # CHECK: FAIL: shtest-shell :: diff-error-2.txt # CHECK: *** TEST 'shtest-shell :: diff-error-2.txt' FAILED *** # CHECK: $ "diff" "temp.txt" # CHECK: # command stderr: -# CHECK: Error: missing or extra operand -# CHECK: error: command failed with exit status: 127 +# CHECK: Error: missing or extra operand +# CHECK: error: command failed with exit status: 1 # CHECK: *** # CHECK: FAIL: shtest-shell :: diff-error-3.txt @@ -134,18 +126,43 @@ # CHECK: *** TEST 'shtest-shell :: diff-error-5.txt' FAILED *** # CHECK: $ "diff" # CHECK: # command stderr: -# CHECK: Error: missing or extra operand -# CHECK: error: command failed with exit status: 127 +# CHECK: Error: missing or extra operand +# CHECK: error: command failed with exit status: 1 # CHECK: *** # CHECK: FAIL: shtest-shell :: diff-error-6.txt # CHECK: *** TEST 'shtest-shell :: diff-error-6.txt' FAILED *** # CHECK: $ "diff" # CHECK: # command stderr: -# CHECK: Error: missing or extra operand -# CHECK: error: command failed with exit status: 127 +# CHECK: Error: missing or extra operand +# CHECK: error: command failed with exit status: 1 +# CHECK: *** + + +# CHECK: FAIL: shtest-shell :: diff-pipes.txt + +# CHECK: *** TEST 'shtest-shell :: diff-pipes.txt' FAILED *** + +# CHECK: $ "diff" "{{[^"]*}}.foo" "{{[^"]*}}.foo" +# CHECK-NOT: note +# CHECK-NOT: error +# CHECK: $ "FileCheck" +# CHECK-NOT: note +# CHECK-NOT: error + +# CHECK: $ "diff" "-u" "{{[^"]*}}.foo" "{{[^"]*}}.bar" +# CHECK: note: command had no output on stdout or stderr +# CHECK: error: command failed with exit status: 1 +# CHECK: $ "FileCheck" +# CHECK-NOT: note +# CHECK-NOT: error +# CHECK: $ "true" + +# CHECK: $ "false" + # CHECK: *** + # CHECK: FAIL: shtest-shell :: diff-r-error-0.txt # CHECK: *** TEST 'shtest-shell :: diff-r-error-0.txt' FAILED *** # CHECK: $ "diff" "-r" @@ -255,23 +272,6 @@ # CHECK: *** -# CHECK: FAIL: shtest-shell :: diff-unified-error-0.txt -# CHECK: *** TEST 'shtest-shell :: diff-unified-error-0.txt' FAILED *** -# CHECK: $ "diff" "-U" "30.1" "{{[^"]*}}" "{{[^"]*}}" -# CHECK: # command stderr: -# CHECK: Error: invalid '-U' argument: 30.1 -# CHECK: error: command failed with exit status: 127 -# CHECK: *** - -# CHECK: FAIL: shtest-shell :: diff-unified-error-1.txt -# CHECK: *** TEST 'shtest-shell :: diff-unified-error-1.txt' FAILED *** -# CHECK: $ "diff" "-U-1" "{{[^"]*}}" "{{[^"]*}}" -# CHECK: # command stderr: -# CHECK: Error: invalid '-U' argument: -1 -# CHECK: error: command failed with exit status: 127 -# CHECK: *** - - # CHECK: FAIL: shtest-shell :: diff-unified.txt # CHECK: *** TEST 'shtest-shell :: diff-unified.txt' FAILED *** @@ -330,6 +330,18 @@ # CHECK-NEXT: error: command failed with exit status: 1 # CHECK-NEXT: $ "true" +# CHECK: $ "diff" "-U" "30.1" "{{[^"]*}}" "{{[^"]*}}" +# CHECK: # command stderr: +# CHECK: Error: invalid '-U' argument: 30.1 +# CHECK: error: command failed with exit status: 1 +# CHECK: $ "true" + +# CHECK: $ "diff" "-U-1" "{{[^"]*}}" "{{[^"]*}}" +# CHECK: # command stderr: +# CHECK: Error: invalid '-U' argument: -1 +# CHECK: error: command failed with exit status: 1 +# CHECK: $ "true" + # CHECK: $ "false" # CHECK: *** @@ -414,4 +426,4 @@ # CHECK: PASS: shtest-shell :: sequencing-0.txt # CHECK: XFAIL: shtest-shell :: sequencing-1.txt # CHECK: PASS: shtest-shell :: valid-shell.txt -# CHECK: Failing Tests (32) +# CHECK: Failing Tests (30) -- 2.40.0