[llvm] r322102 - [lit] Implement "-r" option for builtin "diff" command + a test using that.

Max Moroz via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 9 10:23:34 PST 2018


Author: dor1s
Date: Tue Jan  9 10:23:34 2018
New Revision: 322102

URL: http://llvm.org/viewvc/llvm-project?rev=322102&view=rev
Log:
[lit] Implement "-r" option for builtin "diff" command + a test using that.

Summary:
That would allow to recursively compare directories in tests using
"diff -r" on Windows in a similar way as it can be done on Linux or Mac.

Reviewers: zturner, morehouse, vsk

Reviewed By: zturner

Subscribers: kcc, llvm-commits

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

Added:
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-0.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-1.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-2.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-3.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-4.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-5.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-6.txt
    llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r.txt
Modified:
    llvm/trunk/test/tools/llvm-cov/multithreaded-report.test
    llvm/trunk/utils/lit/lit/TestRunner.py
    llvm/trunk/utils/lit/tests/max-failures.py
    llvm/trunk/utils/lit/tests/shtest-shell.py

Modified: llvm/trunk/test/tools/llvm-cov/multithreaded-report.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/multithreaded-report.test?rev=322102&r1=322101&r2=322102&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/multithreaded-report.test (original)
+++ llvm/trunk/test/tools/llvm-cov/multithreaded-report.test Tue Jan  9 10:23:34 2018
@@ -1,8 +1,5 @@
 # Test "report" command with and without multiple threads.
 
-# Temporarily disable the test on Windows as it doesn't support "diff -r".
-REQUIRES: shell
-
 RUN: llvm-cov report -num-threads=1 \
 RUN:   -path-equivalence=/tmp,%S/Inputs \
 RUN:   -instr-profile %S/Inputs/multithreaded_report/main.profdata \

Modified: llvm/trunk/utils/lit/lit/TestRunner.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/lit/TestRunner.py?rev=322102&r1=322101&r2=322102&view=diff
==============================================================================
--- llvm/trunk/utils/lit/lit/TestRunner.py (original)
+++ llvm/trunk/utils/lit/lit/TestRunner.py Tue Jan  9 10:23:34 2018
@@ -346,14 +346,15 @@ 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, "wbu", ["strip-trailing-cr"])
+        opts, args = getopt.gnu_getopt(args, "wbur", ["strip-trailing-cr"])
     except getopt.GetoptError as err:
         raise InternalShellError(cmd, "Unsupported: 'diff':  %s" % str(err))
 
-    filelines, filepaths = ([] for i in range(2))
+    filelines, filepaths, dir_trees = ([] for i in range(3))
     ignore_all_space = False
     ignore_space_change = False
     unified_diff = False
+    recursive_diff = False
     strip_trailing_cr = False
     for o, a in opts:
         if o == "-w":
@@ -362,6 +363,8 @@ def executeBuiltinDiff(cmd, cmd_shenv):
             ignore_space_change = True
         elif o == "-u":
             unified_diff = True
+        elif o == "-r":
+            recursive_diff = True
         elif o == "--strip-trailing-cr":
             strip_trailing_cr = True
         else:
@@ -370,17 +373,24 @@ def executeBuiltinDiff(cmd, cmd_shenv):
     if len(args) != 2:
         raise InternalShellError(cmd, "Error:  missing or extra operand")
 
-    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))
-            filepaths.append(file)
+    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, 'r') as f:
                 filelines.append(f.readlines())
 
+        exitCode = 0 
         def compose2(f, g):
             return lambda x: f(g(x))
 
@@ -399,6 +409,99 @@ def executeBuiltinDiff(cmd, cmd_shenv):
         for diff in func(filelines[0], filelines[1], filepaths[0], filepaths[1]):
             stdout.write(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

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-0.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-0.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-0.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-0.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,8 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Add two empty files with different names, "diff -r" should fail.
+# RUN: touch %t/dir1/dir1unique
+# RUN: touch %t/dir2/dir2unique
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-1.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-1.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-1.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-1.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,9 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Same filenames in subdirs with different content, "diff -r" should fail.
+# RUN: mkdir -p %t/dir1/subdir %t/dir2/subdir
+# RUN: echo "12345" > %t/dir1/subdir/f01
+# RUN: echo "00000" > %t/dir2/subdir/f01
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-2.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-2.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-2.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-2.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,7 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# An extra file in one of the directories, "diff -r" should fail.
+# RUN: echo extra > %t/dir2/extrafile
+# RUN: diff -r %t/dir1 %t/dir2
\ No newline at end of file

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-3.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-3.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-3.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-3.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,7 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# An extra directory in one of the directories, "diff -r" should fail.
+# RUN: mkdir -p %t/dir1/extra_subdir
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-4.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-4.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-4.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-4.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,8 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Directory vs. File mismatch, "diff -r" should fail.
+# RUN: mkdir -p %t/dir1/extra_subdir
+# RUN: echo ZYX > %t/dir2/extra_subdir
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-5.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-5.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-5.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-5.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,8 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Non-empty extra directory, "diff -r" should fail.
+# RUN: mkdir -p %t/dir1/extra_subdir
+# RUN: echo ZYX > %t/dir1/extra_subdir/extra_file
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-6.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-6.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-6.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r-error-6.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,8 @@
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Empty file vs directory mismatch, diff -r should fail.
+# RUN: echo -n > %t/dir1/extra_file
+# RUN: mkdir -p %t/dir2/extra_file
+# RUN: diff -r %t/dir1 %t/dir2

Added: llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r.txt?rev=322102&view=auto
==============================================================================
--- llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r.txt (added)
+++ llvm/trunk/utils/lit/tests/Inputs/shtest-shell/diff-r.txt Tue Jan  9 10:23:34 2018
@@ -0,0 +1,20 @@
+# Check recursive diff ("diff -r").
+
+# Create two directories for further comparison.
+# RUN: rm -rf %t/dir1 %t/dir2
+# RUN: mkdir -p %t/dir1 %t/dir2
+
+# Create same files in both of the dirs.
+# RUN: echo "hello" > %t/dir1/f1
+# RUN: echo "hello" > %t/dir2/f1
+
+# Create same subdirectories with same contents.
+# RUN: mkdir -p %t/dir1/subdir %t/dir2/subdir
+# RUN: echo "12345" > %t/dir1/subdir/f01
+# RUN: echo "12345" > %t/dir2/subdir/f01
+# RUN: echo -e "xxx\nzzz\nyyy" > %t/dir1/subdir/f02
+# RUN: echo -e "xxx\nzzz\nyyy" > %t/dir2/subdir/f02
+
+# Create empty subdirectories with same names.
+# RUN: mkdir -p %t/dir1/empty_subdir %t/dir2/empty_subdir
+# RUN: diff -r %t/dir1 %t/dir2

Modified: llvm/trunk/utils/lit/tests/max-failures.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/max-failures.py?rev=322102&r1=322101&r2=322102&view=diff
==============================================================================
--- llvm/trunk/utils/lit/tests/max-failures.py (original)
+++ llvm/trunk/utils/lit/tests/max-failures.py Tue Jan  9 10:23:34 2018
@@ -8,7 +8,7 @@
 #
 # END.
 
-# CHECK: Failing Tests (17)
+# CHECK: Failing Tests (24)
 # CHECK: Failing Tests (1)
 # CHECK: Failing Tests (2)
 # CHECK: error: Setting --max-failures to 0 does not have any effect.

Modified: llvm/trunk/utils/lit/tests/shtest-shell.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/tests/shtest-shell.py?rev=322102&r1=322101&r2=322102&view=diff
==============================================================================
--- llvm/trunk/utils/lit/tests/shtest-shell.py (original)
+++ llvm/trunk/utils/lit/tests/shtest-shell.py Tue Jan  9 10:23:34 2018
@@ -71,6 +71,61 @@
 # CHECK: error: command failed with exit status: 127
 # CHECK: ***
 
+# CHECK: FAIL: shtest-shell :: diff-r-error-0.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-0.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: Only in {{.*}}dir1: dir1unique
+# CHECK: Only in {{.*}}dir2: dir2unique
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-1.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-1.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: *** {{.*}}dir1{{.*}}subdir{{.*}}f01
+# CHECK: --- {{.*}}dir2{{.*}}subdir{{.*}}f01
+# CHECK: 12345
+# CHECK: 00000
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-2.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-2.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: Only in {{.*}}dir2: extrafile
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-3.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-3.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: Only in {{.*}}dir1: extra_subdir
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-4.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-4.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: File {{.*}}dir1{{.*}}extra_subdir is a directory while file {{.*}}dir2{{.*}}extra_subdir is a regular file
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-5.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-5.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: Only in {{.*}}dir1: extra_subdir
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: FAIL: shtest-shell :: diff-r-error-6.txt
+# CHECK: *** TEST 'shtest-shell :: diff-r-error-6.txt' FAILED ***
+# CEHCK: $ "diff" "-r" 
+# CHECK: # command output:
+# CHECK: File {{.*}}dir1{{.*}}extra_file is a regular empty file while file {{.*}}dir2{{.*}}extra_file is a directory
+# CHECK: error: command failed with exit status: 1
+
+# CHECK: PASS: shtest-shell :: diff-r.txt
+
 # CHECK: FAIL: shtest-shell :: error-0.txt
 # CHECK: *** TEST 'shtest-shell :: error-0.txt' FAILED ***
 # CHECK: $ "not-a-real-command"
@@ -149,4 +204,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 (17)
+# CHECK: Failing Tests (24)




More information about the llvm-commits mailing list