OSDN Git Service

[lit] Implement 'cat' command for internal shell
authorReid Kleckner <rnk@google.com>
Mon, 26 Mar 2018 18:05:12 +0000 (18:05 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 26 Mar 2018 18:05:12 +0000 (18:05 +0000)
Fixes PR36449

Patch by Chamal de Silva

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328563 91177308-0d34-0410-b5e6-96231b3b80d8

utils/lit/lit/TestRunner.py
utils/lit/lit/builtin_commands/cat.py [new file with mode: 0644]
utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt [new file with mode: 0644]
utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt [new file with mode: 0644]
utils/lit/tests/Inputs/shtest-shell/cat_nonprinting.bin [new file with mode: 0644]
utils/lit/tests/Inputs/shtest-shell/valid-shell.txt
utils/lit/tests/max-failures.py
utils/lit/tests/shtest-shell.py

index dcb552b..93d5c5b 100644 (file)
@@ -156,7 +156,7 @@ def executeShCmd(cmd, shenv, results, timeout=0):
 
 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 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
     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 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
         # 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 @@ 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, "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.
diff --git a/utils/lit/lit/builtin_commands/cat.py b/utils/lit/lit/builtin_commands/cat.py
new file mode 100644 (file)
index 0000000..b4d3d99
--- /dev/null
@@ -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)
diff --git a/utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt b/utils/lit/tests/Inputs/shtest-shell/cat-error-0.txt
new file mode 100644 (file)
index 0000000..690bc1e
--- /dev/null
@@ -0,0 +1,3 @@
+# Check error on an unsupported option for cat .
+#
+# RUN: cat -b temp1.txt
diff --git a/utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt b/utils/lit/tests/Inputs/shtest-shell/cat-error-1.txt
new file mode 100644 (file)
index 0000000..5344707
--- /dev/null
@@ -0,0 +1,3 @@
+# Check error on a unsupported cat (Unable to find input file).
+#
+# RUN: cat temp1.txt
diff --git a/utils/lit/tests/Inputs/shtest-shell/cat_nonprinting.bin b/utils/lit/tests/Inputs/shtest-shell/cat_nonprinting.bin
new file mode 100644 (file)
index 0000000..b4af981
Binary files /dev/null and b/utils/lit/tests/Inputs/shtest-shell/cat_nonprinting.bin differ
index d5cbf86..6cc83e8 100644 (file)
 # 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-?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-?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 8628b68..1613eee 100644 (file)
@@ -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 b3e6a2c..b3d55a0 100644 (file)
 
 # 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 ***
 # 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)