tests: Add regex-based ignore rules for ref files
authorAndreas Sandberg <andreas.sandberg@arm.com>
Fri, 22 Jul 2016 14:24:20 +0000 (15:24 +0100)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Fri, 22 Jul 2016 14:24:20 +0000 (15:24 +0100)
There are cases where we need to ignore files with specific extensions
(e.g., when Mercurial litters the file system with patch
rejects). Implement this functionality using a helper class
(FileIgnoreList) that supports both regular expressions and basic
string comparisons.

Change-Id: I34549754bd2e10ed230ffb2dc057403349f8fa78
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
tests/testing/helpers.py
tests/testing/tests.py

index dcc48904c83a5ebd94b84acadb6809c67ecbb9a3..757167a4b0cb87b7c77d80e38bc95d8c43d20794 100755 (executable)
@@ -40,6 +40,7 @@
 import subprocess
 from threading import Timer
 import time
+import re
 
 class CallTimeoutException(Exception):
     """Exception that indicates that a process call timed out"""
@@ -105,6 +106,47 @@ class ProcessHelper(subprocess.Popen):
         else:
             return status, stdout, stderr
 
+class FileIgnoreList(object):
+    """Helper class to implement file ignore lists.
+
+    This class implements ignore lists using plain string matching and
+    regular expressions. In the simplest use case, rules are created
+    statically upon initialization:
+
+        ignore_list = FileIgnoreList(name=("ignore_me.txt", ), rex=(r".*~", )
+
+    Ignores can be queried using in the same ways as normal Python
+    containers:
+
+        if file_name in ignore_list:
+            print "Ignoring %s" % file_name
+
+
+    New rules can be added at runtime by extending the list in the
+    rules attribute:
+
+        ignore_list.rules.append(FileIgnoreList.simple("bar.txt"))
+    """
+
+    @staticmethod
+    def simple(r):
+        return lambda f: f == r
+
+    @staticmethod
+    def rex(r):
+        re_obj = r if hasattr(r, "search") else re.compile(r)
+        return lambda name: re_obj.search(name)
+
+    def __init__(self, names=(), rex=()):
+        self.rules = [ FileIgnoreList.simple(n) for n in names ] + \
+                     [ FileIgnoreList.rex(r) for r in rex ]
+
+    def __contains__(self, name):
+        for rule in self.rules:
+            if rule(name):
+                return True
+        return False
+
 if __name__ == "__main__":
     # Run internal self tests to ensure that the helpers are working
     # properly. The expected output when running this script is
@@ -129,4 +171,20 @@ if __name__ == "__main__":
     except CallTimeoutException:
         pass
 
+    ignore_list = FileIgnoreList(
+        names=("ignore.txt", "foo/test.txt"),
+        rex=(r"~$", re.compile("^#")))
+
+    assert "ignore.txt" in ignore_list
+    assert "bar.txt" not in ignore_list
+    assert "foo/test.txt" in ignore_list
+    assert "test.txt" not in ignore_list
+    assert "file1.c~" in ignore_list
+    assert "file1.c" not in ignore_list
+    assert "#foo" in ignore_list
+    assert "foo#" not in ignore_list
+
+    ignore_list.rules.append(FileIgnoreList.simple("bar.txt"))
+    assert "bar.txt" in ignore_list
+
     print "SUCCESS!"
index b2b821fd6b859cd934f2ddc42d570e53f21f1fd3..48e034bba8b5c3c99b6cccc31909f96c05cb7e3e 100644 (file)
@@ -224,16 +224,23 @@ class ClassicTest(Test):
     # The diff ignore list contains all files that shouldn't be diffed
     # using DiffOutFile. These files typically use special-purpose
     # diff tools (e.g., DiffStatFile).
-    diff_ignore_files = (
-        # Stat files use a special stat differ
-        "stats.txt",
-    )
+    diff_ignore_files = FileIgnoreList(
+        names=(
+            # Stat files use a special stat differ
+            "stats.txt",
+        ), rex=(
+        ))
 
     # These files should never be included in the list of
     # reference files. This list should include temporary files
     # and other files that we don't care about.
-    ref_ignore_files = (
-    )
+    ref_ignore_files = FileIgnoreList(
+        names=(
+        ), rex=(
+            # Mercurial sometimes leaves backups when applying MQ patches
+            r"\.orig$",
+            r"\.rej$",
+        ))
 
     def __init__(self, gem5, output_dir, config_tuple,
                  timeout=None,