Index: llvm/trunk/utils/lit/lit/TestRunner.py =================================================================== --- llvm/trunk/utils/lit/lit/TestRunner.py +++ llvm/trunk/utils/lit/lit/TestRunner.py @@ -156,7 +156,7 @@ def expand_glob(arg, cwd): if isinstance(arg, GlobItem): - return arg.resolve(cwd) + return sorted(arg.resolve(cwd)) return [arg] def expand_glob_expressions(args, cwd): @@ -745,6 +745,8 @@ stderrTempFiles = [] opened_files = [] named_temp_files = [] + builtin_commands = set(['cat']) + 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 # stderr. @@ -780,15 +782,17 @@ # Resolve the executable path ourselves. args = list(j.args) executable = None - # 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' % j.args[0]) + 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' % j.args[0]) # Replace uses of /dev/null with temporary files. if kAvoidDevNull: @@ -801,6 +805,9 @@ # Expand all glob expressions args = expand_glob_expressions(args, cmd_shenv.cwd) + if is_builtin_cmd: + args.insert(0, "python") + 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. Index: llvm/trunk/utils/lit/lit/builtin_commands/cat.py =================================================================== --- llvm/trunk/utils/lit/lit/builtin_commands/cat.py +++ llvm/trunk/utils/lit/lit/builtin_commands/cat.py @@ -0,0 +1,59 @@ +import getopt +import sys +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + +def convertToCaretAndMNotation(data): + newdata = StringIO() + for char in data: + intval = ord(char) + if intval == 9 or intval == 10: + newdata.write(chr(intval)) + continue + if intval > 127: + intval = intval -128 + newdata.write("M-") + if intval < 32: + newdata.write("^") + newdata.write(chr(intval+64)) + elif intval == 127: + newdata.write("^?") + else: + newdata.write(chr(intval)) + + return newdata.getvalue(); + + +def main(argv): + arguments = argv[1:] + short_options = "v" + long_options = ["show-nonprinting"] + show_nonprinting = False; + + try: + options, filenames = getopt.gnu_getopt(arguments, short_options, long_options) + except getopt.GetoptError as err: + sys.stderr.write("Unsupported: 'cat': %s\n" % str(err)) + sys.exit(1) + + for option, value in options: + if option == "-v" or option == "--show-nonprinting": + show_nonprinting = True; + + for filename in filenames: + try: + fileToCat = open(filename,"rb") + contents = fileToCat.read() + if show_nonprinting: + contents = convertToCaretAndMNotation(contents) + sys.stdout.write(contents) + sys.stdout.flush() + fileToCat.close() + except IOError as error: + sys.stderr.write(str(error)) + sys.exit(1) + +if __name__ == "__main__": + main(sys.argv) Index: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt =================================================================== --- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt +++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt @@ -0,0 +1,3 @@ +# Check error on an unsupported option for cat . +# +# RUN: cat -b temp1.txt Index: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt =================================================================== --- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt +++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt @@ -0,0 +1,3 @@ +# Check error on a unsupported cat (Unable to find input file). +# +# RUN: cat temp1.txt Index: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/valid-shell.txt =================================================================== --- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/valid-shell.txt +++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/valid-shell.txt @@ -85,3 +85,87 @@ # RUN: cd %T/dir1 && echo "hello" > temp1.txt # RUN: cd %T/dir2 && echo "hello" > temp2.txt # RUN: diff temp2.txt ../dir1/temp1.txt +# +# Check cat command with single file. +# +# RUN: rm -rf %T/testCat +# RUN: mkdir -p %T/testCat +# RUN: echo "abcdefgh" > %T/testCat/temp.write +# RUN: cat %T/testCat/temp.write > %T/testCat/tempcat.write +# RUN: "%{python}" %S/check_path.py file %T/testCat/tempcat.write > %T/testCat/path.out +# RUN: FileCheck --check-prefix=FILE-EXISTS < %T/testCat/path.out %s +# RUN: FileCheck --check-prefix=CAT-OUTPUT < %T/testCat/tempcat.write %s +# FILE-EXISTS: True +# CAT-OUTPUT: abcdefgh +# +# Check cat command with multiple files. +# +# RUN: rm -rf %T/testCat +# RUN: mkdir -p %T/testCat +# RUN: echo "abcdefgh" > %T/testCat/temp1.write +# RUN: echo "efghijkl" > %T/testCat/temp2.write +# RUN: echo "mnopqrst" > %T/testCat/temp3.write +# RUN: cat %T/testCat/temp1.write %T/testCat/temp2.write %T/testCat/temp3.write > %T/testCat/tempmulticat.write +# RUN: "%{python}" %S/check_path.py file %T/testCat/tempmulticat.write > %T/testCat/path.out +# RUN: FileCheck --check-prefix=MULTI-FILE-EXISTS < %T/testCat/path.out %s +# RUN: FileCheck --check-prefix=MULTI-CAT-OUTPUT < %T/testCat/tempmulticat.write %s +# MULTI-FILE-EXISTS: True +# MULTI-CAT-OUTPUT: abcdefgh +# MULTI-CAT-OUTPUT-NEXT: efghijkl +# MULTI-CAT-OUTPUT-NEXT: mnopqrst +# +# Check cat command with multiple files and piped output to FileCheck. +# +# RUN: rm -rf %T/testCat +# RUN: mkdir -p %T/testCat +# RUN: echo "abcdefgh" > %T/testCat/temp1.write +# RUN: echo "efghijkl" > %T/testCat/temp2.write +# RUN: cat %T/testCat/temp1.write %T/testCat/temp2.write | FileCheck --check-prefix=PIPED-CAT-OUTPUT %s +# PIPED-CAT-OUTPUT: abcdefgh +# PIPED-CAT-OUTPUT-NEXT: efghijkl +# +# Check cat command with multiple files and glob expressions. +# +# RUN: rm -rf %T/testCat +# RUN: mkdir -p %T/testCat +# RUN: echo "cvbnm" > %T/testCat/temp1.write +# RUN: echo "qwerty" > %T/testCat/temp2.write +# RUN: cat %T/testCat/*.write | FileCheck --check-prefix=GLOB-CAT-OUTPUT %s +# GLOB-CAT-OUTPUT: cvbnm +# GLOB-CAT-OUTPUT-NEXT: qwerty +# +# Check cat command with -v option +# +# RUN: cat -v %S/cat_nonprinting.bin | FileCheck --check-prefix=NP-CAT-OUTPUT %s +# NP-CAT-OUTPUT: ^@^A^B^C^D^E^F^G ^H +# NP-CAT-OUTPUT-NEXT: ^K^L^M^N^O^P^Q^R^S +# NP-CAT-OUTPUT-NEXT: ^T^U^V^W^X^Y^Z^[^\^]^^^_ !"#$%&' +# NP-CAT-OUTPUT-NEXT: ()*+,-./0123456789:; +# NP-CAT-OUTPUT-NEXT: <=>?@ABCDEFGHIJKLMNO +# NP-CAT-OUTPUT-NEXT: PQRSTUVWXYZ[\]^_`abc +# NP-CAT-OUTPUT-NEXT: defghijklmnopqrstuvw +# NP-CAT-OUTPUT-NEXT: xyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^K +# NP-CAT-OUTPUT-NEXT: M-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\M-^]M-^^M-^_ +# NP-CAT-OUTPUT-NEXT: M- M-!M-"M-#M-$M-%M-&M-'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3 +# NP-CAT-OUTPUT-NEXT: M-4M-5M-6M-7M-8M-9M-:M-;M-M-?M-@M-AM-BM-CM-DM-EM-FM-G +# NP-CAT-OUTPUT-NEXT: M-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[ +# NP-CAT-OUTPUT-NEXT: M-\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-o +# NP-CAT-OUTPUT-NEXT: M-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^? +# +# Check cat command with -show-nonprinting option +# +# RUN: cat --show-nonprinting %S/cat_nonprinting.bin | FileCheck --check-prefix=NPLONG-CAT-OUTPUT %s +# NPLONG-CAT-OUTPUT: ^@^A^B^C^D^E^F^G ^H +# NPLONG-CAT-OUTPUT-NEXT: ^K^L^M^N^O^P^Q^R^S +# NPLONG-CAT-OUTPUT-NEXT: ^T^U^V^W^X^Y^Z^[^\^]^^^_ !"#$%&' +# NPLONG-CAT-OUTPUT-NEXT: ()*+,-./0123456789:; +# NPLONG-CAT-OUTPUT-NEXT: <=>?@ABCDEFGHIJKLMNO +# NPLONG-CAT-OUTPUT-NEXT: PQRSTUVWXYZ[\]^_`abc +# NPLONG-CAT-OUTPUT-NEXT: defghijklmnopqrstuvw +# NPLONG-CAT-OUTPUT-NEXT: xyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^K +# NPLONG-CAT-OUTPUT-NEXT: M-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\M-^]M-^^M-^_ +# NPLONG-CAT-OUTPUT-NEXT: M- M-!M-"M-#M-$M-%M-&M-'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3 +# NPLONG-CAT-OUTPUT-NEXT: M-4M-5M-6M-7M-8M-9M-:M-;M-M-?M-@M-AM-BM-CM-DM-EM-FM-G +# NPLONG-CAT-OUTPUT-NEXT: M-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[ +# NPLONG-CAT-OUTPUT-NEXT: M-\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-o +# NPLONG-CAT-OUTPUT-NEXT: M-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^? Index: llvm/trunk/utils/lit/tests/max-failures.py =================================================================== --- llvm/trunk/utils/lit/tests/max-failures.py +++ llvm/trunk/utils/lit/tests/max-failures.py @@ -8,7 +8,7 @@ # # END. -# CHECK: Failing Tests (24) +# CHECK: Failing Tests (26) # CHECK: Failing Tests (1) # CHECK: Failing Tests (2) # CHECK: error: Setting --max-failures to 0 does not have any effect. Index: llvm/trunk/utils/lit/tests/shtest-shell.py =================================================================== --- llvm/trunk/utils/lit/tests/shtest-shell.py +++ llvm/trunk/utils/lit/tests/shtest-shell.py @@ -10,6 +10,21 @@ # CHECK: -- Testing: +# CHECK: FAIL: shtest-shell :: cat-error-0.txt +# CHECK: *** TEST 'shtest-shell :: cat-error-0.txt' FAILED *** +# CHECK: $ "cat" "-b" "temp1.txt" +# CHECK: # command stderr: +# CHECK: Unsupported: 'cat': option -b not recognized +# CHECK: error: command failed with exit status: 1 +# CHECK: *** + +# CHECK: FAIL: shtest-shell :: cat-error-1.txt +# CHECK: *** TEST 'shtest-shell :: cat-error-1.txt' FAILED *** +# CHECK: $ "cat" "temp1.txt" +# CHECK: # command stderr: +# CHECK: [Errno 2] No such file or directory: 'temp1.txt' +# CHECK: error: command failed with exit status: 1 +# CHECK: *** # CHECK: FAIL: shtest-shell :: diff-error-0.txt # CHECK: *** TEST 'shtest-shell :: diff-error-0.txt' FAILED *** @@ -204,4 +219,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 (24) +# CHECK: Failing Tests (26)